summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Gutov <dgutov@yandex.ru>2022-08-15 02:22:59 +0300
committerDmitry Gutov <dgutov@yandex.ru>2022-08-15 02:22:59 +0300
commitee3a674c7c9e39fe7ff296ce1f9830fc45520de8 (patch)
treee8ba1e7be54314f208454e80e3d31044c913f3eb
parentfe0e53d963899a16e0dd1bbc1ba10a6b59f7989e (diff)
parent0a8e88fd83db5398d36064a7f87cff5b57da7284 (diff)
downloademacs-scratch/font_lock_large_files.tar.gz
Merge branch 'master' into scratch/font_lock_large_filesscratch/font_lock_large_files
-rw-r--r--admin/authors.el2
-rwxr-xr-xadmin/emake2
-rw-r--r--admin/unidata/unidata-gen.el4
-rw-r--r--doc/emacs/glossary.texi4
-rw-r--r--doc/emacs/misc.texi96
-rw-r--r--doc/emacs/msdos.texi6
-rw-r--r--doc/lispintro/emacs-lisp-intro.texi45
-rw-r--r--doc/lispref/debugging.texi44
-rw-r--r--doc/lispref/display.texi6
-rw-r--r--doc/lispref/functions.texi8
-rw-r--r--doc/lispref/loading.texi2
-rw-r--r--doc/lispref/objects.texi3
-rw-r--r--doc/lispref/os.texi10
-rw-r--r--doc/lispref/processes.texi1
-rw-r--r--doc/misc/auth.texi10
-rw-r--r--doc/misc/calc.texi2
-rw-r--r--doc/misc/efaq-w32.texi6
-rw-r--r--doc/misc/efaq.texi28
-rw-r--r--doc/misc/emacs-mime.texi6
-rw-r--r--doc/misc/eshell.texi82
-rw-r--r--doc/misc/gnus-faq.texi217
-rw-r--r--doc/misc/gnus.texi102
-rw-r--r--doc/misc/htmlfontify.texi10
-rw-r--r--doc/misc/idlwave.texi11
-rw-r--r--doc/misc/message.texi11
-rw-r--r--doc/misc/mh-e.texi13
-rw-r--r--doc/misc/tramp.texi4
-rw-r--r--doc/misc/viper.texi4
-rw-r--r--etc/AUTHORS2
-rw-r--r--etc/NEWS71
-rw-r--r--etc/PROBLEMS17
-rw-r--r--lisp/array.el87
-rw-r--r--lisp/bookmark.el2
-rw-r--r--lisp/calc/calc-vec.el4
-rw-r--r--lisp/calc/calc.el12
-rw-r--r--lisp/calendar/time-date.el12
-rw-r--r--lisp/cedet/cedet.el6
-rw-r--r--lisp/cedet/ede.el9
-rw-r--r--lisp/cedet/ede/emacs.el1
-rw-r--r--lisp/cedet/semantic.el6
-rw-r--r--lisp/cedet/semantic/bovine.el4
-rw-r--r--lisp/cedet/semantic/db-file.el2
-rw-r--r--lisp/cedet/semantic/wisent/comp.el2
-rw-r--r--lisp/cedet/srecode.el4
-rw-r--r--lisp/descr-text.el4
-rw-r--r--lisp/emacs-lisp/advice.el19
-rw-r--r--lisp/emacs-lisp/byte-opt.el57
-rw-r--r--lisp/emacs-lisp/bytecomp.el24
-rw-r--r--lisp/emacs-lisp/checkdoc.el21
-rw-r--r--lisp/emacs-lisp/cl-macs.el2
-rw-r--r--lisp/emacs-lisp/ert.el3
-rw-r--r--lisp/emacs-lisp/helper.el1
-rw-r--r--lisp/emacs-lisp/loaddefs-gen.el35
-rw-r--r--lisp/emacs-lisp/macroexp.el2
-rw-r--r--lisp/emacs-lisp/nadvice.el24
-rw-r--r--lisp/emacs-lisp/package.el2
-rw-r--r--lisp/emacs-lisp/pcase.el13
-rw-r--r--lisp/emacs-lisp/ring.el4
-rw-r--r--lisp/emacs-lisp/seq.el20
-rw-r--r--lisp/emacs-lisp/subr-x.el22
-rw-r--r--lisp/emulation/viper.el2
-rw-r--r--lisp/eshell/em-alias.el2
-rw-r--r--lisp/eshell/esh-cmd.el85
-rw-r--r--lisp/eshell/esh-io.el50
-rw-r--r--lisp/eshell/esh-proc.el68
-rw-r--r--lisp/faces.el33
-rw-r--r--lisp/finder.el16
-rw-r--r--lisp/gnus/deuglify.el1
-rw-r--r--lisp/gnus/gnus-diary.el6
-rw-r--r--lisp/gnus/gnus-util.el8
-rw-r--r--lisp/gnus/gnus-uu.el3
-rw-r--r--lisp/gnus/gnus.el3
-rw-r--r--lisp/gnus/message.el9
-rw-r--r--lisp/gnus/mm-decode.el9
-rw-r--r--lisp/gnus/mml.el3
-rw-r--r--lisp/gnus/nnagent.el1
-rw-r--r--lisp/gnus/nnbabyl.el1
-rw-r--r--lisp/gnus/nndiary.el2
-rw-r--r--lisp/gnus/nndir.el1
-rw-r--r--lisp/gnus/nndoc.el1
-rw-r--r--lisp/gnus/nndraft.el1
-rw-r--r--lisp/gnus/nneething.el1
-rw-r--r--lisp/gnus/nnfolder.el1
-rw-r--r--lisp/gnus/nnmaildir.el1
-rw-r--r--lisp/gnus/nnmbox.el1
-rw-r--r--lisp/gnus/nnmh.el1
-rw-r--r--lisp/gnus/nnml.el1
-rw-r--r--lisp/gnus/nnrss.el1
-rw-r--r--lisp/gnus/nnspool.el1
-rw-r--r--lisp/gnus/nntp.el1
-rw-r--r--lisp/gnus/nnvirtual.el1
-rw-r--r--lisp/help-fns.el10
-rw-r--r--lisp/htmlfontify.el11
-rw-r--r--lisp/international/characters.el23
-rw-r--r--lisp/leim/quail/indian.el2
-rw-r--r--lisp/loadup.el3
-rw-r--r--lisp/mh-e/mh-e.el4
-rw-r--r--lisp/net/newst-treeview.el11
-rw-r--r--lisp/net/tramp-adb.el2
-rw-r--r--lisp/net/tramp-archive.el2
-rw-r--r--lisp/net/tramp-compat.el23
-rw-r--r--lisp/net/tramp-crypt.el2
-rw-r--r--lisp/net/tramp-gvfs.el7
-rw-r--r--lisp/net/tramp-sh.el47
-rw-r--r--lisp/org/org.el5
-rw-r--r--lisp/outline.el10
-rw-r--r--lisp/play/5x5.el12
-rw-r--r--lisp/printing.el44
-rw-r--r--lisp/progmodes/ebnf2ps.el51
-rw-r--r--lisp/progmodes/f90.el7
-rw-r--r--lisp/progmodes/gdb-mi.el28
-rw-r--r--lisp/progmodes/gud.el13
-rw-r--r--lisp/progmodes/js.el7
-rw-r--r--lisp/progmodes/ps-mode.el8
-rw-r--r--lisp/ps-print.el39
-rw-r--r--lisp/select.el9
-rw-r--r--lisp/simple.el35
-rw-r--r--lisp/subr.el6
-rw-r--r--lisp/textmodes/emacs-authors-mode.el145
-rw-r--r--lisp/textmodes/emacs-news-mode.el13
-rw-r--r--lisp/textmodes/etc-authors-mode.el133
-rw-r--r--lisp/thingatpt.el13
-rw-r--r--lisp/vc/add-log.el14
-rw-r--r--lisp/vc/diff-mode.el4
-rw-r--r--lisp/vc/ediff-mult.el26
-rw-r--r--lisp/vc/ediff.el11
-rw-r--r--lisp/vc/emerge.el2
-rw-r--r--lisp/vc/vc-annotate.el30
-rw-r--r--lisp/vc/vc-bzr.el24
-rw-r--r--lisp/vc/vc-dir.el16
-rw-r--r--lisp/vc/vc-git.el57
-rw-r--r--lisp/vc/vc-hg.el11
-rw-r--r--lisp/vc/vc-hooks.el57
-rw-r--r--src/Makefile.in1
-rw-r--r--src/buffer.c21
-rw-r--r--src/eval.c59
-rw-r--r--src/ftcrfont.c6
-rw-r--r--src/indent.c60
-rw-r--r--src/keyboard.c25
-rw-r--r--src/lisp.h2
-rw-r--r--src/timefns.c71
-rw-r--r--src/window.c9
-rw-r--r--src/xdisp.c203
-rw-r--r--src/xfns.c19
-rw-r--r--src/xterm.c250
-rw-r--r--test/lisp/emacs-lisp/seq-tests.el7
-rw-r--r--test/lisp/eshell/esh-cmd-tests.el283
-rw-r--r--test/lisp/eshell/esh-var-tests.el59
-rw-r--r--test/lisp/eshell/eshell-tests.el53
-rw-r--r--test/lisp/international/ucs-normalize-tests.el2
-rw-r--r--test/lisp/net/tramp-tests.el3
151 files changed, 2125 insertions, 1533 deletions
diff --git a/admin/authors.el b/admin/authors.el
index de43d914544..12fe25fa4e1 100644
--- a/admin/authors.el
+++ b/admin/authors.el
@@ -1883,7 +1883,7 @@ list of their contributions.\n")
(insert "\n "))
(insert " " file))
(insert "\n")))))
- (insert "\nLocal" " Variables:\nmode: etc-authors\ncoding: "
+ (insert "\nLocal" " Variables:\nmode: emacs-authors\ncoding: "
(symbol-name authors-coding-system) "\nEnd:\n")
(message "Generating buffer %s... done" buffer-name)
(unless noninteractive
diff --git a/admin/emake b/admin/emake
index 9bebd340678..548611c6afc 100755
--- a/admin/emake
+++ b/admin/emake
@@ -29,6 +29,7 @@ s#^Running # Running #
s#^Configured for # Configured for #
s#^./temacs.*# \\& #
s#^make.*Error# \\& #
+s#^Dumping under the name# \\& #
' | \
grep -E --line-buffered -v "^make|\
^Loading|\
@@ -43,7 +44,6 @@ GEN.*autoloads|\
^Adding name|\
^Dump mode|\
^Dumping finger|\
-^Dumping under the name|\
^Byte counts|\
^Reloc counts|\
^Pure-hashed|\
diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el
index 0a9fd5108ce..78dd1c37288 100644
--- a/admin/unidata/unidata-gen.el
+++ b/admin/unidata/unidata-gen.el
@@ -1083,8 +1083,8 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)."
(defun unidata--ensure-compiled (&rest funcs)
(dolist (fun funcs)
- (or (byte-code-function-p (symbol-function fun))
- (byte-compile fun))))
+ (unless (compiled-function-p (symbol-function fun))
+ (byte-compile fun))))
(defun unidata-gen-table-name (prop index &rest _ignore)
(let* ((table (unidata-gen-table-word-list prop index 'unidata-split-name))
diff --git a/doc/emacs/glossary.texi b/doc/emacs/glossary.texi
index 5224e313407..9a537019974 100644
--- a/doc/emacs/glossary.texi
+++ b/doc/emacs/glossary.texi
@@ -1457,8 +1457,8 @@ level by aborting (q.v.@:) and quitting (q.v.). @xref{Quitting}.
@item Transient Mark Mode
The default behavior of the mark (q.v.@:) and region (q.v.), in which
setting the mark activates it and highlights the region, is called
-Transient Mark mode. In GNU Emacs 23 and onwards, it is enabled by
-default. @xref{Disabled Transient Mark}.
+Transient Mark mode. It is enabled by default. @xref{Disabled
+Transient Mark}.
@item Transposition
Transposing two units of text means putting each one into the place
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index 841a285520a..da1b87b48bd 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -1,6 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2022 Free Software
-@c Foundation, Inc.
+@c Copyright (C) 1985--2022 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@iftex
@chapter Miscellaneous Commands
@@ -2870,99 +2869,6 @@ new major mode which provides a command to switch back. These
approaches give you more flexibility to go back to unfinished tasks in
the order you choose.
-@ignore
-@c Apart from edt and viper, this is all obsolete.
-@c (Can't believe we were saying "most other editors" into 2014!)
-@c There seems no point having a node just for those, which both have
-@c their own manuals.
-@node Emulation
-@section Emulation
-@cindex emulating other editors
-@cindex other editors
-@cindex EDT
-@cindex vi
-@cindex WordStar
-
- GNU Emacs can be programmed to emulate (more or less) most other
-editors. Standard facilities can emulate these:
-
-@table @asis
-@item CRiSP/Brief (PC editor)
-@findex crisp-mode
-@vindex crisp-override-meta-x
-@findex scroll-all-mode
-@cindex CRiSP mode
-@cindex Brief emulation
-@cindex emulation of Brief
-@cindex mode, CRiSP
-@kbd{M-x crisp-mode} enables key bindings to emulate the CRiSP/Brief
-editor. Note that this rebinds @kbd{M-x} to exit Emacs unless you set
-the variable @code{crisp-override-meta-x}. You can also use the
-command @kbd{M-x scroll-all-mode} or set the variable
-@code{crisp-load-scroll-all} to emulate CRiSP's scroll-all feature
-(scrolling all windows together).
-
-@item EDT (DEC VMS editor)
-@findex edt-emulation-on
-@findex edt-emulation-off
-Turn on EDT emulation with @kbd{M-x edt-emulation-on}; restore normal
-command bindings with @kbd{M-x edt-emulation-off}.
-
-Most of the EDT emulation commands are keypad keys, and most standard
-Emacs key bindings are still available. The EDT emulation rebindings
-are done in the global keymap, so there is no problem switching
-buffers or major modes while in EDT emulation.
-
-@item TPU (DEC VMS editor)
-@findex tpu-edt-on
-@cindex TPU
-@kbd{M-x tpu-edt-on} turns on emulation of the TPU editor emulating EDT.
-
-@item vi (Berkeley editor)
-@findex viper-mode
-Viper is an emulator for vi. It implements several levels of
-emulation; level 1 is closest to vi itself, while level 5 departs
-somewhat from strict emulation to take advantage of the capabilities of
-Emacs. To invoke Viper, type @kbd{M-x viper-mode}; it will guide you
-the rest of the way and ask for the emulation level. @inforef{Top,
-Viper, viper}.
-
-@item vi (another emulator)
-@findex vi-mode
-@kbd{M-x vi-mode} enters a major mode that replaces the previously
-established major mode. All of the vi commands that, in real vi, enter
-input mode are programmed instead to return to the previous major
-mode. Thus, ordinary Emacs serves as vi's input mode.
-
-Because vi emulation works through major modes, it does not work
-to switch buffers during emulation. Return to normal Emacs first.
-
-If you plan to use vi emulation much, you probably want to bind a key
-to the @code{vi-mode} command.
-
-@item vi (alternate emulator)
-@findex vip-mode
-@kbd{M-x vip-mode} invokes another vi emulator, said to resemble real vi
-more thoroughly than @kbd{M-x vi-mode}. Input mode in this emulator
-is changed from ordinary Emacs so you can use @key{ESC} to go back to
-emulated vi command mode. To get from emulated vi command mode back to
-ordinary Emacs, type @kbd{C-z}.
-
-This emulation does not work through major modes, and it is possible
-to switch buffers in various ways within the emulator. It is not
-so necessary to assign a key to the command @code{vip-mode} as
-it is with @code{vi-mode} because terminating insert mode does
-not use it.
-
-@inforef{Top, VIP, vip}, for full information.
-
-@item WordStar (old wordprocessor)
-@findex wordstar-mode
-@kbd{M-x wordstar-mode} provides a major mode with WordStar-like
-key bindings.
-@end table
-@end ignore
-
@node Hyperlinking
@section Hyperlinking and Web Navigation Features
diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index e30d623a77c..dd0787cd38d 100644
--- a/doc/emacs/msdos.texi
+++ b/doc/emacs/msdos.texi
@@ -986,9 +986,9 @@ printer, put this in your @file{.emacs} file:
@section Specifying Fonts on MS-Windows
@cindex font specification (MS Windows)
- Starting with Emacs 23, fonts are specified by their name, size
-and optional properties. The format for specifying fonts comes from the
-fontconfig library used in modern Free desktops:
+ Fonts are specified by their name, size and optional properties.
+The format for specifying fonts comes from the fontconfig library used
+in modern Free desktops:
@example
[Family[-PointSize]][:Option1=Value1[:Option2=Value2[...]]]
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index 049c8a65a8f..47a5a870fde 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -2020,7 +2020,6 @@ the arguments to the function @code{concat} are the strings
@w{@code{"The "}} and @w{@code{" red foxes."}} and the list
@code{(number-to-string (+ 2 fill-column))}.
-@c For GNU Emacs 22, need number-to-string
@smallexample
(concat "The " (number-to-string (+ 2 fill-column)) " red foxes.")
@end smallexample
@@ -10297,9 +10296,8 @@ loop with a list.
@cindex @file{*scratch*} buffer
The function requires several lines for its output. If you are
-reading this in a recent instance of GNU Emacs,
-@c GNU Emacs 21, GNU Emacs 22, or a later version,
-you can evaluate the following expression inside of Info, as usual.
+reading this in a recent instance of GNU Emacs, you can evaluate the
+following expression inside of Info, as usual.
If you are using an earlier version of Emacs, you need to copy the
necessary expressions to your @file{*scratch*} buffer and evaluate
@@ -15134,16 +15132,16 @@ Emacs may produce different results.)
@end group
@group
-(lengths-list-file "./lisp/makesum.el")
- @result{} (85 181)
+(lengths-list-file "./lisp/hex-util.el")
+ @result{} (82 71)
@end group
@group
(recursive-lengths-list-many-files
'("./lisp/macros.el"
"./lisp/mail/mailalias.el"
- "./lisp/makesum.el"))
- @result{} (283 263 480 90 38 32 29 95 178 180 321 218 324 85 181)
+ "./lisp/hex-util.el"))
+ @result{} (283 263 480 90 38 32 29 95 178 180 321 218 324 82 71)
@end group
@end smallexample
@@ -15235,27 +15233,13 @@ Sorting the list returned by the
@code{recursive-lengths-list-many-files} function is straightforward;
it uses the @code{<} function:
-@ignore
-2006 Oct 29
-In GNU Emacs 22, eval
-(progn
- (cd "/usr/local/share/emacs/22.0.50/")
- (sort
- (recursive-lengths-list-many-files
- '("./lisp/macros.el"
- "./lisp/mail/mailalias.el"
- "./lisp/makesum.el"))
- '<))
-
-@end ignore
-
@smallexample
@group
(sort
(recursive-lengths-list-many-files
'("./lisp/macros.el"
"./lisp/mailalias.el"
- "./lisp/makesum.el"))
+ "./lisp/hex-util.el"))
'<)
@end group
@end smallexample
@@ -15265,7 +15249,7 @@ In GNU Emacs 22, eval
which produces:
@smallexample
-(29 32 38 85 90 95 178 180 181 218 263 283 321 324 480)
+(29 32 38 71 82 90 95 178 180 218 263 283 321 324 480)
@end smallexample
@noindent
@@ -15313,7 +15297,7 @@ as a list that looks like this (but with more elements):
@group
("./lisp/macros.el"
"./lisp/mail/rmail.el"
- "./lisp/makesum.el")
+ "./lisp/hex-util.el")
@end group
@end smallexample
@@ -17711,17 +17695,6 @@ or start GNU Emacs with the command @code{emacs -nbc}.
(setq grep-command "grep -i -nH -e ")
@end smallexample
-@ignore
-@c Evidently, no longer needed in GNU Emacs 22
-
-item Automatically uncompress compressed files when visiting them
-
-smallexample
-(load "uncompress")
-end smallexample
-
-@end ignore
-
@item Find an existing buffer, even if it has a different name@*
This avoids problems with symbolic links.
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 058c9319544..9ae40949d1e 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -77,6 +77,7 @@ debugger recursively. @xref{Recursive Editing}.
@menu
* Error Debugging:: Entering the debugger when an error happens.
+* Debugging Redisplay:: Getting backtraces from redisplay errors.
* Infinite Loops:: Stopping and debugging a program that doesn't exit.
* Function Debugging:: Entering it when a certain function is called.
* Variable Debugging:: Entering it when a variable is modified.
@@ -105,6 +106,10 @@ debugger, set the variable @code{debug-on-error} to non-@code{nil}.
(The command @code{toggle-debug-on-error} provides an easy way to do
this.)
+Note that, for technical reasons, you cannot use the facilities
+defined in this subsection to debug errors in Lisp that the redisplay
+code has invoked. @xref{Debugging Redisplay}, for help with these.
+
@defopt debug-on-error
This variable determines whether the debugger is called when an error
is signaled and not handled. If @code{debug-on-error} is @code{t},
@@ -213,6 +218,45 @@ file, use the option @samp{--debug-init}. This binds
bypasses the @code{condition-case} which normally catches errors in the
init file.
+@node Debugging Redisplay
+@subsection Debugging Redisplay Errors
+@cindex redisplay errors
+@cindex debugging redisplay errors
+
+When an error occurs in Lisp code which redisplay has invoked, Emacs's
+usual debugging mechanisms are unusable, for technical reasons. This
+subsection describes how to get a backtrace from such an error, which
+should be helpful in debugging it.
+
+These directions apply to Lisp forms used, for example, in
+@code{:eval} mode line constructs (@pxref{Mode Line Data}), and in all
+hooks invoked from redisplay, such as:
+
+@itemize
+@item
+@code{fontification-functions} (@pxref{Auto Faces}).
+@item
+@code{window-scroll-functions} (@pxref{Window Hooks}).
+@end itemize
+
+Note that if you have had an error in a hook function called from
+redisplay, the error handling might have removed this function from
+the hook. You will thus need to reinitialize that hook somehow,
+perhaps with @code{add-hook}, to be able to replay the bug.
+
+To generate a backtrace in these circumstances, set the variable
+@code{backtrace-on-redisplay-error} to non-@code{nil}. When the error
+occurs, Emacs will dump the backtrace to the buffer
+@file{*Redisplay-trace*}, but won't automatically display it in a
+window. This is to avoid needlessly corrupting the redisplay you are
+debugging. You will thus need to display the buffer yourself, with a
+command such as @code{switch-to-buffer-other-frame} @key{C-x 5 b}.
+
+@defvar backtrace-on-redisplay-error
+Set this variable to non-@code{nil} to enable the generation of a
+backtrace when an error occurs in any Lisp called from redisplay.
+@end defvar
+
@node Infinite Loops
@subsection Debugging Infinite Loops
@cindex infinite loops
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index ace67fbedb7..96079dc106a 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -8596,9 +8596,9 @@ Characters of Unicode General Category [Cf], such as U+200E
images, such as U+00AD @sc{soft hyphen}.
@item variation-selectors
-Unicode VS-1 through VS-16 (U+FE00 through U+FE0F), which are used to
-select between different glyphs for the same codepoints (typically
-emojis).
+Unicode VS-1 through VS-256 (U+FE00 through U+FE0F and U+E0100 through
+U+E01EF), which are used to select between different glyphs for the same
+codepoints (typically emojis).
@item no-font
Characters for which there is no suitable font, or which cannot be
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 8265e58210e..ddf7cff6c2e 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -217,6 +217,14 @@ function. For example:
@end example
@end defun
+@defun compiled-function-p object
+This function returns @code{t} if @var{object} is a function object
+that was either built-in (a.k.a.@: ``primitive'', @pxref{What Is a
+Function}), or byte-compiled (@pxref{Byte Compilation}), or
+natively-compiled (@pxref{Native Compilation}), or a function loaded
+from a dynamic module (@pxref{Dynamic Modules}).
+@end defun
+
@defun subr-arity subr
This works like @code{func-arity}, but only for built-in functions and
without symbol indirection. It signals an error for non-built-in
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi
index 0972a7a123c..4e4f12dc324 100644
--- a/doc/lispref/loading.texi
+++ b/doc/lispref/loading.texi
@@ -440,7 +440,7 @@ similarly-named file in a directory earlier on @code{load-path}.
For instance, suppose @code{load-path} is set to
@example
- ("/opt/emacs/site-lisp" "/usr/share/emacs/23.3/lisp")
+ ("/opt/emacs/site-lisp" "/usr/share/emacs/29.1/lisp")
@end example
@noindent
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index 1bae1924557..7b5e9adee29 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -2022,6 +2022,9 @@ with references to further information.
@item byte-code-function-p
@xref{Byte-Code Type, byte-code-function-p}.
+@item compiled-function-p
+@xref{Byte-Code Type, compiled-function-p}.
+
@item case-table-p
@xref{Case Tables, case-table-p}.
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index d591b219cd0..35828018417 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1544,11 +1544,11 @@ as traditional Gregorian years do; for example, the year number
@defun time-convert time form
This function converts a time value into a Lisp timestamp.
-The optional @var{form} argument specifies the timestamp form to be
-returned. If @var{form} is the symbol @code{integer}, this function
-returns an integer count of seconds. If @var{form} is a positive
-integer, it specifies a clock frequency and this function returns an
-integer-pair timestamp @code{(@var{ticks} . @var{form})}. If @var{form} is
+The @var{form} argument specifies the timestamp form to be returned.
+If @var{form} is the symbol @code{integer}, this function returns an
+integer count of seconds. If @var{form} is a positive integer, it
+specifies a clock frequency and this function returns an integer-pair
+timestamp @code{(@var{ticks} . @var{form})}. If @var{form} is
@code{t}, this function treats it as a positive integer suitable for
representing the timestamp; for example, it is treated as 1000000000
if @var{time} is @code{nil} and the platform timestamp has nanosecond
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 382053ab24a..db6b4c35ef7 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -1960,7 +1960,6 @@ because @var{seconds} can be floating point to specify
waiting a fractional number of seconds. If @var{seconds} is 0, the
function accepts whatever output is pending but does not wait.
-@c Emacs 22.1 feature
If @var{process} is a process, and the argument @var{just-this-one} is
non-@code{nil}, only output from that process is handled, suspending output
from other processes until some output has been received from that
diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi
index 829d7f4fa03..91a9afd9c9f 100644
--- a/doc/misc/auth.texi
+++ b/doc/misc/auth.texi
@@ -652,14 +652,8 @@ before @file{~/.authinfo}, the auth-source library will try to
read the GnuPG encrypted @file{.gpg} file first, before
the unencrypted file.
-In Emacs 23 or later there is an option @code{auto-encryption-mode} to
-automatically decrypt @file{*.gpg} files. It is enabled by default.
-If you are using earlier versions of Emacs, you will need:
-
-@lisp
-(require 'epa-file)
-(epa-file-enable)
-@end lisp
+There is an option @code{auto-encryption-mode} to automatically
+decrypt @file{*.gpg} files. It is enabled by default.
If you want your GnuPG passwords to be cached, set up @code{gpg-agent}
or EasyPG Assistant
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index 9bda6af1c5b..98f59b89c01 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -1,7 +1,7 @@
\input texinfo @c -*- mode: texinfo; coding: utf-8 -*-
+@setfilename ../../info/calc.info
@comment %**start of header (This is for running Texinfo on a region.)
@c smallbook
-@setfilename ../../info/calc.info
@c [title]
@settitle GNU Emacs Calc Manual
@include docstyle.texi
diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi
index 084b5a3254e..46c257e42e5 100644
--- a/doc/misc/efaq-w32.texi
+++ b/doc/misc/efaq-w32.texi
@@ -930,9 +930,9 @@ an indication of whether the font is outline (.TTF, .ATM) or raster (.FON)
based when fonts are listed, which may let you differentiate between two
fonts with the same name and different technologies.
-Starting with Emacs 23, the preferred font name format will be moving
-to the simpler and more flexible fontconfig format. XLFD names will
-continue to be supported for backward compatibility.
+Starting with Emacs 23, the preferred font name format is the simpler
+and more flexible fontconfig format. XLFD names will continue to be
+supported for backward compatibility.
@example
XLFD: -*-Courier New-normal-r-*-*-13-*-*-*-c-*-iso8859-1
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index a98c4b6a614..c29e4fe4875 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -2891,20 +2891,20 @@ and cause an annoying delay in display, so several features exist to
work around this.
@cindex Just-In-Time syntax highlighting
-In Emacs 21 and later, turning on @code{font-lock-mode} automatically
-activates the new @dfn{Just-In-Time fontification} provided by
-@code{jit-lock-mode}. @code{jit-lock-mode} defers the fontification of
-portions of buffer until you actually need to see them, and can also
-fontify while Emacs is idle. This makes display of the visible portion
-of a buffer almost instantaneous. For details about customizing
-@code{jit-lock-mode}, type @kbd{C-h f jit-lock-mode @key{RET}}.
+Turning on @code{font-lock-mode} automatically activates
+@dfn{Just-In-Time fontification} provided by @code{jit-lock-mode}.
+@code{jit-lock-mode} defers the fontification of portions of buffer
+until you actually need to see them, and can also fontify while Emacs
+is idle. This makes display of the visible portion of a buffer almost
+instantaneous. For details about customizing @code{jit-lock-mode},
+type @kbd{C-h f jit-lock-mode @key{RET}}.
@cindex Levels of syntax highlighting
@cindex Decoration level, in @code{font-lock-mode}
-In versions of Emacs before 21, different levels of decoration are
-available, from slight to gaudy. More decoration means you need to wait
-more time for a buffer to be fontified (or a faster machine). To
-control how decorated your buffers should become, set the value of
+Different levels of decoration are available, from slight to gaudy.
+More decoration means you need to wait more time for a buffer to be
+fontified (or a faster machine). To control how decorated your
+buffers should become, set the value of
@code{font-lock-maximum-decoration} in your @file{.emacs} file, with a
@code{nil} value indicating default (usually minimum) decoration, and a
@code{t} value indicating the maximum decoration. For the gaudiest
@@ -2985,11 +2985,7 @@ Add the following line to your @file{.emacs} file:
In many systems, @code{ls} is aliased to @samp{ls --color}, which
prints using ANSI color escape sequences. Emacs includes the
@code{ansi-color} package, which lets Shell mode recognize these
-escape sequences. In Emacs 23.2 and later, the package is enabled by
-default; in earlier versions you can enable it by typing @kbd{M-x
-ansi-color-for-comint-mode} in the Shell buffer, or by adding
-@code{(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)} to
-your init file.
+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?
diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi
index 640712edf33..5f4e1a639be 100644
--- a/doc/misc/emacs-mime.texi
+++ b/doc/misc/emacs-mime.texi
@@ -403,9 +403,9 @@ This selects the function used to render @acronym{HTML}. The
predefined renderers are selected by the symbols @code{shr},
@code{gnus-w3m}, @code{w3m}@footnote{See
@uref{http://emacs-w3m.namazu.org/} for more information about
-emacs-w3m}, @code{links}, @code{lynx}, @code{w3m-standalone} or
-@code{html2text}. You can also specify a function, which will be
-called with a @acronym{MIME} handle as the argument.
+emacs-w3m}, @code{links}, @code{lynx}, or @code{w3m-standalone}. You
+can also specify a function, which will be called with a
+@acronym{MIME} handle as the argument.
@item mm-html-inhibit-images
@vindex mm-html-inhibit-images
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 9f9c88582f3..13f13163dd7 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -201,7 +201,7 @@ history and invoking commands in a script file.
* Aliases::
* History::
* Completion::
-* for loop::
+* Control Flow::
* Scripts::
@end menu
@@ -219,12 +219,18 @@ same name; if there is no match, it then tries to execute it as an
external command.
The semicolon (@code{;}) can be used to separate multiple command
-invocations on a single line. A command invocation followed by an
-ampersand (@code{&}) will be run in the background. Eshell has no job
-control, so you can not suspend or background the current process, or
-bring a background process into the foreground. That said, background
-processes invoked from Eshell can be controlled the same way as any
-other background process in Emacs.
+invocations on a single line. You can also separate commands with
+@code{&&} or @code{||}. When using @code{&&}, Eshell will execute the
+second command only if the first succeeds (i.e.@: has an exit
+status of 0); with @code{||}, Eshell will execute the second command
+only if the first fails.
+
+A command invocation followed by an ampersand (@code{&}) will be run
+in the background. Eshell has no job control, so you can not suspend
+or background the current process, or bring a background process into
+the foreground. That said, background processes invoked from Eshell
+can be controlled the same way as any other background process in
+Emacs.
@node Arguments
@section Arguments
@@ -884,14 +890,18 @@ command (excluding the command name itself).
@vindex $$
@item $$
-This is the result of the last command. In case of an external
-command, it is @code{t} or @code{nil}.
+This is the result of the last command. For external commands, it is
+@code{t} if the exit code was 0 or @code{nil} otherwise.
+@vindex eshell-lisp-form-nil-is-failure
@vindex $?
@item $?
This variable contains the exit code of the last command. If the last
command was a Lisp function, it is 0 for successful completion or 1
-otherwise.
+otherwise. If @code{eshell-lisp-form-nil-is-failure} is
+non-@code{nil}, then a command with a Lisp form, like
+@samp{(@var{command} @var{args}@dots{})}, that returns @code{nil} will
+set this variable to 2.
@vindex $COLUMNS
@vindex $LINES
@@ -1008,19 +1018,46 @@ command for which this function provides completions; you can also name
the function @code{pcomplete/MAJOR-MODE/COMMAND} to define completions
for a specific major mode.
-@node for loop
-@section @code{for} loop
+@node Control Flow
+@section Control Flow
Because Eshell commands can not (easily) be combined with lisp forms,
-Eshell provides a command-oriented @command{for}-loop for convenience.
-The syntax is as follows:
+Eshell provides command-oriented control flow statements for
+convenience.
-@example
-@code{for VAR in TOKENS @{ command invocation(s) @}}
-@end example
+Most of Eshell's control flow statements accept a @var{conditional}.
+This can take a few different forms. If @var{conditional} is a dollar
+expansion, the condition is satisfied if the result is a
+non-@code{nil} value. If @var{conditional} is a @samp{@{
+@var{subcommand} @}} or @samp{(@var{lisp form})}, the condition is
+satisfied if the command's exit status is 0.
+
+@table @code
+
+@item if @var{conditional} @{ @var{true-commands} @}
+@itemx if @var{conditional} @{ @var{true-commands} @} @{ @var{false-commands} @}
+Evaluate @var{true-commands} if @var{conditional} is satisfied;
+otherwise, evaluate @var{false-commands}.
+
+@item unless @var{conditional} @{ @var{false-commands} @}
+@itemx unless @var{conditional} @{ @var{false-commands} @} @{ @var{true-commands} @}
+Evaluate @var{false-commands} if @var{conditional} is not satisfied;
+otherwise, evaluate @var{true-commands}.
-where @samp{TOKENS} is a space-separated sequence of values of
-@var{VAR} for each iteration. This can even be the output of a
-command if @samp{TOKENS} is replaced with @samp{@{ command invocation @}}.
+@item while @var{conditional} @{ @var{commands} @}
+Repeatedly evaluate @var{commands} so long as @var{conditional} is
+satisfied.
+
+@item until @var{conditional} @{ @var{commands} @}
+Repeatedly evaluate @var{commands} until @var{conditional} is
+satisfied.
+
+@item for @var{var} in @var{list}@dots{} @{ @var{commands} @}
+Iterate over each element of of @var{list}, storing the element in
+@var{var} and evaluating @var{commands}. If @var{list} is not a list,
+treat it as a list of one element. If you specify multiple
+@var{lists}, this will iterate over each of them in turn.
+
+@end table
@node Scripts
@section Scripts
@@ -1811,11 +1848,6 @@ scrolls back.
@item Menu support was removed, but never put back
-@item Using C-p and C-n with rebind gets into a locked state
-
-This happened a few times in Emacs 21, but has been irreproducible
-since.
-
@item If an interactive process is currently running, @kbd{M-!} doesn't work
@item Use a timer instead of @code{sleep-for} when killing child processes
diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi
index 4923efb3dbe..c442ca1bacd 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, 2001--2022 Free Software Foundation, Inc.
+@c Copyright (C) 1995--2022 Free Software Foundation, Inc.
@c
@c @setfilename gnus-faq.info
@c @settitle Frequently Asked Questions
@@ -13,7 +13,6 @@
@section Frequently Asked Questions
@menu
-* FAQ - Changes::
* FAQ - Introduction:: About Gnus and this FAQ.
* FAQ 1 - Installation FAQ:: Installation of Gnus.
* FAQ 2 - Startup / Group buffer:: Start up questions and the
@@ -41,21 +40,6 @@ This is the new Gnus Frequently Asked Questions list.
Please submit features and suggestions to the
@email{ding@@gnus.org, ding list}.
-@node FAQ - Changes
-@subsection Changes
-
-
-
-@itemize @bullet
-
-@item
-2008-06-15: Adjust for message-fill-column. Add x-face-file.
-Clarify difference between ding and gnu.emacs.gnus. Remove
-reference to discontinued service.
-
-@item
-2006-04-15: Added tip on how to delete sent buffer on exit.
-@end itemize
@node FAQ - Introduction
@subsection Introduction
@@ -63,11 +47,11 @@ reference to discontinued service.
This is the Gnus Frequently Asked Questions list.
Gnus is a Usenet Newsreader and Electronic Mail User Agent implemented
-as a part of Emacs. It's been around in some form for almost a decade
-now, and has been distributed as a standard part of Emacs for much of
-that time. Gnus 5 is the latest (and greatest) incarnation. The
+as a part of Emacs. It's been around in some form since the early
+1990s, and has been distributed as a standard part of Emacs for much
+of that time. Gnus 5 is the latest (and greatest) incarnation. The
original version was called GNUS, and was written by Masanobu UMEDA@.
-When autumn crept up in '94, Lars Magne Ingebrigtsen grew bored and
+When autumn crept up in 1994, Lars Magne Ingebrigtsen grew bored and
decided to rewrite Gnus.
Its biggest strength is the fact that it is extremely
@@ -84,11 +68,6 @@ would like to thank Steve Baur and Per Abrahamsen for doing a wonderful
job with this FAQ before him. We would like to do the same: thanks,
Justin!
-This version is much nicer than the unofficial hypertext
-versions that are archived at Utrecht, Oxford, Smart Pages, Ohio
-State, and other FAQ archives. See the resources question below
-if you want information on obtaining it in another format.
-
The information contained here was compiled with the assistance
of the Gnus development mailing list, and any errors or
misprints are the Gnus team's fault, sorry.
@@ -98,11 +77,9 @@ misprints are the Gnus team's fault, sorry.
@menu
* FAQ 1-1:: What is the latest version of Gnus?
-* FAQ 1-2:: What's new in 5.10?
-* FAQ 1-3:: Where and how to get Gnus?
-* FAQ 1-4:: I sometimes read references to No Gnus and Oort Gnus,
+* FAQ 1-2:: Where and how to get Gnus?
+* FAQ 1-3:: I sometimes read references to No Gnus and Oort Gnus,
what are those?
-* FAQ 1-5:: Which version of Emacs do I need?
@end menu
@node FAQ 1-1
@@ -112,80 +89,28 @@ What is the latest version of Gnus?
@subsubheading Answer
-Jingle please: Gnus 5.10 is released, get it while it's
-hot! As well as the step in version number is rather
-small, Gnus 5.10 has tons of new features which you
-shouldn't miss. The current release (5.13) should be at
-least as stable as the latest release of the 5.8 series.
+The latest version of Gnus is bundled with Emacs.
@node FAQ 1-2
@subsubheading Question 1.2
-What's new in 5.10?
-
-@subsubheading Answer
-
-First of all, you should have a look into the file
-GNUS-NEWS in the toplevel directory of the Gnus tarball,
-there the most important changes are listed. Here's a
-short list of the changes I find especially
-important/interesting:
-
-@itemize @bullet
-
-@item
-Major rewrite of the Gnus agent, Gnus agent is now
-active by default.
-
-@item
-Many new article washing functions for dealing with
-ugly formatted articles.
-
-@item
-Anti Spam features.
-
-@item
-Message-utils now included in Gnus.
-
-@item
-New format specifiers for summary lines, e.g., %B for
-a complex trn-style thread tree.
-@end itemize
-
-@node FAQ 1-3
-@subsubheading Question 1.3
-
Where and how to get Gnus?
@subsubheading Answer
Gnus is bundled with Emacs.
-@node FAQ 1-4
-@subsubheading Question 1.4
+@node FAQ 1-3
+@subsubheading Question 1.3
I sometimes read references to No Gnus and Oort Gnus,
what are those?
@subsubheading Answer
-Oort Gnus was the name of the development version of
-Gnus, which became Gnus 5.10 in autumn 2003. No Gnus is
-the name of the current development version which will
-once become Gnus 5.12 or Gnus 6. (If you're wondering why
-not 5.11, the odd version numbers are normally used for
-the Gnus versions bundled with Emacs)
-
-@node FAQ 1-5
-@subsubheading Question 1.5
-
-Which version of Emacs do I need?
-
-@subsubheading Answer
-
-Gnus 5.13 requires an Emacs version that is greater than or equal
-to Emacs 23.1, although there are some features that
-only work on Emacs 24.
+Oort Gnus was the name of the development version of Gnus, which
+became Gnus 5.10 in autumn 2003. No Gnus was the name of the
+development version that became Gnus 5.12.
@node FAQ 2 - Startup / Group buffer
@subsection Startup / Group buffer
@@ -718,9 +643,8 @@ in @file{~/.gnus.el} to load enough old articles to prevent teared threads, repl
all articles (Warning: Both settings enlarge the amount of data which is
fetched when you enter a group and slow down the process of entering a group).
-If you already use Gnus 5.10, you can say
-@samp{/o N}
-In summary buffer to load the last N messages, this feature is not available in 5.8.8
+You can say @samp{/o N} in the summary buffer to load the last N
+messages.
If you don't want all old messages, but the parent of the message you're just reading,
you can say @samp{^}, if you want to retrieve the whole thread
@@ -820,11 +744,10 @@ Can I use some other browser than w3m to render my HTML-mails?
@subsubheading Answer
-Only if you use Gnus 5.10 or younger. In this case you've got the
-choice between shr, w3m, links, lynx and html2text, which
-one is used can be specified in the variable
-mm-text-html-renderer, so if you want links to render your
-mail say
+You've got the choice between @samp{shr}, @samp{w3m}, @samp{links},
+and @samp{lynx}. Which one is used is specified in the variable
+@code{mm-text-html-renderer}, so if you want links to render your
+mail, say:
@example
(setq mm-text-html-renderer 'links)
@@ -847,8 +770,7 @@ long lines'' (@samp{W w}), ``Decode ROT13''
the dumb quoting used by many users of Microsoft products
(@samp{W Y f} gives you full deuglify.
See @samp{W Y C-h} or have a look at the menus for
-other deuglifications). Outlook deuglify is only available since
-Gnus 5.10.
+other deuglifications).
@node FAQ 4-9
@subsubheading Question 4.9
@@ -1038,7 +960,7 @@ you'll find useful things like positioning the cursor and
tabulators which allow you a summary in table form, but
sadly hard tabulators are broken in 5.8.8.
-Since 5.10, Gnus offers you some very nice new specifiers,
+Gnus offers you some very nice new specifiers,
e.g., %B which draws a thread-tree and %&user-date which
gives you a date where the details are dependent of the
articles age. Here's an example which uses both:
@@ -1245,7 +1167,7 @@ How to set stuff like From, Organization, Reply-To, signature...?
@subsubheading Answer
There are other ways, but you should use posting styles
-for this. (See below why).
+for this. (See below why.)
This example should make the syntax clear:
@example
@@ -1329,19 +1251,14 @@ Is there a spell-checker? Perhaps even on-the-fly spell-checking?
@subsubheading Answer
-You can use ispell.el to spell-check stuff in Emacs. So the
-first thing to do is to make sure that you've got either
-@uref{https://www.cs.hmc.edu/~geoff/ispell.html, ispell}
-or @uref{http://aspell.net, aspell}
-installed and in your Path. Then you need
-ispell.el
-and for on-the-fly spell-checking
-@uref{https://www-sop.inria.fr/members/Manuel.Serrano/flyspell/flyspell.html, flyspell.el}.
-Ispell.el is shipped with Emacs,
-flyspell.el is shipped with Emacs, so there should be no need to install them
-manually.
+You can use ispell.el to spell-check stuff in Emacs, and flyspell.el
+for on-the-fly spell-checking. So the first thing to do is to make
+sure that you've got either
+@uref{https://hunspell.github.io/, hunspell},
+@uref{https://www.cs.hmc.edu/~geoff/ispell.html, ispell} or
+@uref{http://aspell.net, aspell} installed and in your Path.
-Ispell.el assumes you use ispell, if you choose aspell say
+Ispell.el assumes you use ispell. If you use aspell say
@example
(setq ispell-program-name "aspell")
@@ -1494,14 +1411,14 @@ Now you only have to tell Gnus to include the X-face in your postings by saying
@end example
@noindent
-in @file{~/.gnus.el}. If you use Gnus 5.10, you can simply add an entry
+in @file{~/.gnus.el}. You can add an entry
@example
(x-face-file "~/.xface")
@end example
@noindent
-to gnus-posting-styles.
+to @code{gnus-posting-styles}.
@node FAQ 5-9
@subsubheading Question 5.9
@@ -1519,21 +1436,6 @@ Put this in @file{~/.gnus.el}:
@end example
@noindent
-if you already use Gnus 5.10, if you still use 5.8.8 or
-5.9 try this instead:
-
-@example
-(with-eval-after-load "gnus-msg"
- (unless (boundp 'gnus-confirm-mail-reply-to-news)
- (defadvice gnus-summary-reply (around reply-in-news activate)
- "Request confirmation when replying to news."
- (interactive)
- (when (or (not (gnus-news-group-p gnus-newsgroup-name))
- (y-or-n-p "Really reply by mail to article author?"))
- ad-do-it))))
-@end example
-@noindent
-
@node FAQ 5-10
@subsubheading Question 5.10
@@ -1541,14 +1443,7 @@ How to tell Gnus not to generate a sender header?
@subsubheading Answer
-Since 5.10 Gnus doesn't generate a sender header by
-default. For older Gnus' try this in @file{~/.gnus.el}:
-
-@example
-(with-eval-after-load "message"
- (add-to-list 'message-syntax-checks '(sender . disabled)))
-@end example
-@noindent
+Gnus doesn't generate a sender header by default.
@node FAQ 5-11
@subsubheading Question 5.11
@@ -1729,7 +1624,7 @@ more then one article."
You can now say @samp{M-x
my-archive-article} in summary buffer to
archive the article under the cursor in a nnml
-group. (Change nnml to your preferred back end)
+group. (Change nnml to your preferred back end.)
Of course you can also make sure the cache is enabled by saying
@@ -1756,7 +1651,7 @@ if you found the posting there, tell Google to display
the raw message, look for the message-id, and say
@samp{M-^ the@@message.id @key{RET}} in a
summary buffer.
-Since Gnus 5.10 there's also a Gnus interface for
+There's a Gnus interface for
groups.google.com which you can call with
@samp{G W}) in group buffer.
@@ -1770,25 +1665,6 @@ instead. Further on there are the
gnus-summary-limit-to-foo functions, which can help you,
too.
-Of course you can also use grep to search through your
-local mail, but this is both slow for big archives and
-inconvenient since you are not displaying the found mail
-in Gnus. Here nnir comes into action. Nnir is a front end
-to search engines like swish-e or swish++ and
-others. You index your mail with one of those search
-engines and with the help of nnir you can search through
-the indexed mail and generate a temporary group with all
-messages which met your search criteria. If this sounds
-cool to you, get nnir.el from
-@c FIXME Isn't this file in Gnus?
-@ignore
-@c Dead link 2013/7.
-@uref{ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/}
-or
-@end ignore
-@uref{ftp://ftp.is.informatik.uni-duisburg.de/pub/src/emacs/}.
-Instructions on how to use it are at the top of the file.
-
@node FAQ 6-4
@subsubheading Question 6.4
@@ -1937,16 +1813,9 @@ So what was this thing about the Agent?
The Gnus agent is part of Gnus, it allows you to fetch
mail and news and store them on disk for reading them
later when you're offline. It kind of mimics offline
-newsreaders like Forte Agent. If you want to use
-the Agent place the following in @file{~/.gnus.el} if you are
-still using 5.8.8 or 5.9 (it's the default since 5.10):
+newsreaders like Forte Agent. It is enabled by default.
-@example
-(setq gnus-agent t)
-@end example
-@noindent
-
-Now you've got to select the servers whose groups can be
+You've got to select the servers whose groups can be
stored locally. To do this, open the server buffer
(that is press @samp{^} while in the
group buffer). Now select a server by moving point to
@@ -2161,12 +2030,12 @@ How to speed up the process of entering a group?
@subsubheading Answer
-A speed killer is setting the variable
-gnus-fetch-old-headers to anything different from @code{nil},
-so don't do this if speed is an issue.
+A speed killer is setting the variable @code{gnus-fetch-old-headers}
+to anything different from @code{nil}, so don't do this if speed is an
+issue.
-You could increase the value of gc-cons-threshold
-by saying something like
+You could increase the value of @code{gc-cons-threshold} by saying
+something like:
@example
(setq gc-cons-threshold 3500000)
@@ -2204,10 +2073,6 @@ between core Gnus and the real NNTP-, POP3-, IMAP- or
whatever-server which offers Gnus a standardized interface
to functions like "get message", "get Headers" etc.
-@item Emacs
-When the term Emacs is used in this FAQ, it means GNU
-Emacs.
-
@item Message
In this FAQ message means either a mail or a posting to a
Usenet Newsgroup or to some other fancy back end, no matter
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 7da90dfb1d6..c5298d8ef59 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -885,8 +885,6 @@ History
* Why?:: What's the point of Gnus?
* Compatibility:: Just how compatible is Gnus with @sc{gnus}?
* Conformity:: Gnus tries to conform to all standards.
-* Emacsen:: Gnus can be run on a few modern Emacsen.
-* Gnus Development:: How Gnus is developed.
* Contributors:: Oodles of people.
* New Features:: Pointers to some of the new stuff in Gnus.
@@ -8621,14 +8619,6 @@ uuencoded files that have had trailing spaces deleted.
@vindex gnus-uu-pre-uudecode-hook
Hook run before sending a message to @code{uudecode}.
-@item gnus-uu-view-with-metamail
-@vindex gnus-uu-view-with-metamail
-@cindex metamail
-Non-@code{nil} means that @code{gnus-uu} will ignore the viewing
-commands defined by the rule variables and just fudge a @acronym{MIME}
-content type based on the file name. The result will be fed to
-@code{metamail} for viewing.
-
@item gnus-uu-save-in-digest
@vindex gnus-uu-save-in-digest
Non-@code{nil} means that @code{gnus-uu}, when asked to save without
@@ -9364,9 +9354,6 @@ Use @uref{https://almende.github.io/chap-links-library/, CHAP Links}.
@item lynx
Use @uref{https://lynx.browser.org/, Lynx}.
-@item html2text
-Use html2text---a simple @acronym{HTML} converter included with Gnus.
-
@end table
@item W D F
@@ -15440,8 +15427,6 @@ files. If a positive number, delete files older than number of days
(the deletion will only happen when receiving new mail). You may also
set @code{mail-source-delete-incoming} to @code{nil} and call
@code{mail-source-delete-old-incoming} from a hook or interactively.
-@code{mail-source-delete-incoming} defaults to @code{10} in alpha Gnusae
-and @code{2} in released Gnusae. @xref{Gnus Development}.
@item mail-source-delete-old-incoming-confirm
@vindex mail-source-delete-old-incoming-confirm
@@ -21962,7 +21947,7 @@ you can set up a local @acronym{IMAP} server, which you then access via
@code{nnimap}. This is a rather massive setup for accessing some mbox
files, so just change to MH or Maildir already... However, if you're
really, really passionate about using mbox, you might want to look into
-the package @file{mairix.el}, which comes with Emacs 23.
+the package @file{mairix.el}, which comes with Emacs.
@node What nnmairix does
@subsection What nnmairix does
@@ -26919,8 +26904,6 @@ renamed it back again to ``Gnus''. But in mixed case. ``Gnus'' vs.
* Why?:: What's the point of Gnus?
* Compatibility:: Just how compatible is Gnus with @sc{gnus}?
* Conformity:: Gnus tries to conform to all standards.
-* Emacsen:: Gnus can be run on a few modern Emacsen.
-* Gnus Development:: How Gnus is developed.
* Contributors:: Oodles of people.
* New Features:: Pointers to some of the new stuff in Gnus.
@end menu
@@ -27035,16 +27018,6 @@ maintains a hash table that points to the entries in this alist (which
speeds up many functions), and changing the alist directly will lead to
peculiar results.
-@cindex hilit19
-@cindex highlighting
-Old hilit19 code does not work at all. In fact, you should probably
-remove all hilit code from all Gnus hooks
-(@code{gnus-group-prepare-hook} and @code{gnus-summary-prepare-hook}).
-Gnus provides various integrated functions for highlighting. These are
-faster and more accurate. To make life easier for everybody, Gnus will
-by default remove all hilit calls from all hilit hooks. Uncleanliness!
-Away!
-
Packages like @code{expire-kill} will no longer work. As a matter of
fact, you should probably remove all old @sc{gnus} packages (and other
code) when you start using Gnus. More likely than not, Gnus already
@@ -27147,79 +27120,6 @@ mentioned above, don't hesitate to drop a note to Gnus Towers and let us
know.
-@node Emacsen
-@subsection Emacsen
-@cindex Emacsen
-@cindex Mule
-@cindex Emacs
-
-This version of Gnus should work on:
-
-@itemize @bullet
-
-@item
-Emacs 23.1 and up.
-
-@end itemize
-
-This Gnus version will absolutely not work on any Emacsen older than
-that. Not reliably, at least. Older versions of Gnus may work on older
-Emacs versions. Particularly, Gnus 5.10.8 should also work on Emacs
-20.7.
-
-@c No-merge comment: The paragraph added in v5-10 here must not be
-@c synced here!
-
-@node Gnus Development
-@subsection Gnus Development
-
-Gnus is developed in a two-phased cycle. The first phase involves much
-discussion on the development mailing list @samp{ding@@gnus.org}, where people
-propose changes and new features, post patches and new back ends. This
-phase is called the @dfn{alpha} phase, since the Gnusae released in this
-phase are @dfn{alpha releases}, or (perhaps more commonly in other
-circles) @dfn{snapshots}. During this phase, Gnus is assumed to be
-unstable and should not be used by casual users. Gnus alpha releases
-have names like ``Oort Gnus'' and ``No Gnus''. @xref{Gnus Versions}.
-
-After futzing around for 10--100 alpha releases, Gnus is declared
-@dfn{frozen}, and only bug fixes are applied. Gnus loses the prefix,
-and is called things like ``Gnus 5.10.1'' instead. Normal people are
-supposed to be able to use these, and these are mostly discussed on the
-@samp{gnu.emacs.gnus} newsgroup. This newgroup is mirrored to the
-mailing list @samp{info-gnus-english@@gnu.org} which is carried on Gmane
-as @samp{gmane.emacs.gnus.user}. These releases are finally integrated
-in Emacs.
-
-@cindex Incoming*
-@vindex mail-source-delete-incoming
-Some variable defaults differ between alpha Gnusae and released Gnusae,
-in particular, @code{mail-source-delete-incoming}. This is to prevent
-lossage of mail if an alpha release hiccups while handling the mail.
-@xref{Mail Source Customization}.
-
-The division of discussion between the ding mailing list and the Gnus
-newsgroup is not purely based on publicity concerns. It's true that
-having people write about the horrible things that an alpha Gnus release
-can do (sometimes) in a public forum may scare people off, but more
-importantly, talking about new experimental features that have been
-introduced may confuse casual users. New features are frequently
-introduced, fiddled with, and judged to be found wanting, and then
-either discarded or totally rewritten. People reading the mailing list
-usually keep up with these rapid changes, while people on the newsgroup
-can't be assumed to do so.
-
-So if you have problems with or questions about the alpha versions,
-direct those to the ding mailing list @samp{ding@@gnus.org}. This list
-is also available on Gmane as @samp{gmane.emacs.gnus.general}.
-
-@cindex Incoming*
-@vindex mail-source-delete-incoming
-Some variable defaults differ between alpha Gnusae and released Gnusae,
-in particular, @code{mail-source-delete-incoming}. This is to prevent
-lossage of mail if an alpha release hiccups while handling the mail.
-@xref{Mail Source Customization}.
-
@node Contributors
@subsection Contributors
@cindex contributors
diff --git a/doc/misc/htmlfontify.texi b/doc/misc/htmlfontify.texi
index 0ab000b70f1..fadc6a5cbe3 100644
--- a/doc/misc/htmlfontify.texi
+++ b/doc/misc/htmlfontify.texi
@@ -10,8 +10,7 @@
This manual documents Htmlfontify, a source code -> crosslinked +
formatted + syntax colorized html transformer.
-Copyright @copyright{} 2002--2003, 2013--2022 Free Software Foundation,
-Inc.
+Copyright @copyright{} 2002--2022 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -1540,13 +1539,6 @@ Htmlfontify has a couple of external requirements:
@itemize @bullet
@item
-GNU Emacs 20.7+ or 21.1+
-
-Other versions may work---these have been used successfully by the
-author. If you intend to use Htmlfontify in batch mode, 21.1+ is
-pretty much required.
-
-@item
A copy of etags (exuberant-ctags or GNU etags). Htmlfontify attempts
to autodetect the version you have and customize itself accordingly,
but you should be able to override this.
diff --git a/doc/misc/idlwave.texi b/doc/misc/idlwave.texi
index 6aaa4309a16..0ba87b2e58b 100644
--- a/doc/misc/idlwave.texi
+++ b/doc/misc/idlwave.texi
@@ -4116,17 +4116,6 @@ configuration files (e.g., @file{.cshrc}), but from the file
@file{~/.MacOSX/environment.plist}. Either include your path settings
there, or start Emacs and IDLWAVE from the shell.
-@item @strong{I'm getting errors like @samp{Symbol's value as variable is void:
-cl-builtin-gethash} on completion or routine info.}
-
-This error arises if you upgraded Emacs from 20.x to 21.x without
-re-installing IDLWAVE@. Old Emacs and new Emacs are not byte-compatible
-in compiled lisp files. Presumably, you kept the original .elc files in
-place, and this is the source of the error. If you recompile (or just
-"make; make install") from source, it should resolve this problem.
-Another option is to recompile the @file{idlw*.el} files by hand using
-@kbd{M-x byte-compile-file}.
-
@item @strong{@kbd{M-@key{TAB}} doesn't complete words, it switches
windows on my desktop.}
diff --git a/doc/misc/message.texi b/doc/misc/message.texi
index 29fbdfe1786..49e3faed7b1 100644
--- a/doc/misc/message.texi
+++ b/doc/misc/message.texi
@@ -1152,12 +1152,11 @@ programs are required to make things work, and some small general hints.
@uref{https://www.gnupg.org/, GNU Privacy Guard} or
@uref{https://www.openssl.org/, OpenSSL}. The default Emacs interface
to the S/MIME implementation is EasyPG (@pxref{Top,,EasyPG Assistant
-User's Manual, epa, EasyPG Assistant User's Manual}), which has been
-included in Emacs since version 23 and which relies on the command
-line tool @command{gpgsm} provided by @acronym{GnuPG}. That tool
-implements certificate management, including certificate revocation
-and expiry, while such tasks need to be performed manually, if OpenSSL
-is used.
+User's Manual, epa, EasyPG Assistant User's Manual}), which is
+included in Emacs and relies on the command line tool @command{gpgsm}
+provided by @acronym{GnuPG}. That tool implements certificate
+management, including certificate revocation and expiry, while such
+tasks need to be performed manually, if OpenSSL is used.
The choice between EasyPG and OpenSSL is controlled by the variable
@code{mml-smime-use}, which needs to be set to the value @code{epg}
diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi
index 12841860d91..6a948ce2ca8 100644
--- a/doc/misc/mh-e.texi
+++ b/doc/misc/mh-e.texi
@@ -213,8 +213,8 @@ more niceties about GNU Emacs and MH@. Now I'm fully hooked on both of
them.
The MH-E package is distributed with Emacs@footnote{Version
-@value{VERSION} of MH-E appeared in Emacs 24.4. It is supported in GNU
-Emacs 23 and higher. It is compatible with MH versions 6.8.4 and
+@value{VERSION} of MH-E appeared in Emacs 24.4.
+It is compatible with MH versions 6.8.4 and
higher, all versions of nmh, and GNU mailutils 1.0 and higher}, so you
shouldn't have to do anything special to use it. Gnus is also
required; version 5.10 or higher is recommended. This manual covers
@@ -1488,7 +1488,7 @@ Binding} of @samp{m}.
@cindex Unix commands, @command{xbuffy}
You can use @command{xbuffy} to automate the incorporation of this
-mail using the Emacs 23 command @command{emacsclient} as follows:
+mail using the Emacs command @command{emacsclient} as follows:
@smallexample
box ~/mail/mh-e
@@ -2553,13 +2553,6 @@ produces pretty nice output, and it highlights links. It renders
@samp{&ndash;} and @samp{&reg;} okay. It sometimes fails to wrap lines
properly. It always downloads remote images.
@c -------------------------
-@cindex browser, @samp{html2text}
-@cindex @samp{html2text}
-@item @samp{html2text}
-The @samp{html2text} browser requires an external program. Some users
-have reported problems with it, such as filling the entire message as
-if it were one paragraph, or displaying chunks of raw HTML.
-@c -------------------------
@cindex browser, @samp{links}
@cindex @samp{links}
@item @samp{links}
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index cfbc96f4692..924aa66d444 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -3383,7 +3383,7 @@ names. Beside the @code{default} value, @var{syntax} can be
@item @code{simplified}
@cindex simplified syntax
-The remote file name syntax is similar to the syntax used by Ange FTP@.
+This remote file name syntax is similar to the syntax used by Ange FTP@.
A remote file name has the form
@code{@value{prefix}user@@host@value{postfix}path/to/file}. The
@code{user@@} part is optional, and the method is determined by
@@ -3395,7 +3395,7 @@ A remote file name has the form
@clear unified
@set separate
@include trampver.texi
-The remote file name syntax is similar to the syntax used by XEmacs.
+This remote file name syntax originated in the XEmacs text editor.
A remote file name has the form
@code{@trampfn{method,user@@host,path/to/file}}. The @code{method}
and @code{user@@} parts are optional.
diff --git a/doc/misc/viper.texi b/doc/misc/viper.texi
index b0deb31d108..0703667ecce 100644
--- a/doc/misc/viper.texi
+++ b/doc/misc/viper.texi
@@ -1842,7 +1842,7 @@ usually most effective:
(set-face-background viper-replace-overlay-face "yellow")
@end smallexample
For a complete list of colors available to you, evaluate the expression
-@code{(x-defined-colors)}. (Type it in the buffer @file{*scratch*} and then
+@code{(defined-colors)}. (Type it in the buffer @file{*scratch*} and then
hit the @kbd{C-j} key.
@item viper-replace-overlay-cursor-color "Red"
@@ -2571,7 +2571,7 @@ The GNU Emacs Manual}, for more information on tags.
The following two commands are normally bound to a mouse click and are part
of Viper. They work only if Emacs runs as an application under X
-Windows (or under some other window system for which a port of GNU Emacs 20
+Windows (or under some other window system for which a port of GNU Emacs
is available). Clicking the mouse when Emacs is invoked in an Xterm window
(using @code{emacs -nw}) will do no good.
diff --git a/etc/AUTHORS b/etc/AUTHORS
index 4ad8a54130d..f6349df5bc2 100644
--- a/etc/AUTHORS
+++ b/etc/AUTHORS
@@ -6062,6 +6062,6 @@ Zoran Milojevic: changed avoid.el
উৎসব রায়: changed quail/indian.el
Local Variables:
-mode: etc-authors
+mode: emacs-authors
coding: utf-8
End:
diff --git a/etc/NEWS b/etc/NEWS
index 8d54ccc0dc8..c982684d3a9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -385,6 +385,10 @@ longer choke when a buffer on display contains long lines. The
variable 'long-line-threshold' controls whether and when these display
optimizations are in effect.
+A companion variable 'large-hscroll-threshold' controls when another
+set of display optimizations are in effect, which are aimed
+specifically at speeding up display of long lines that are truncated.
+
If you still experience slowdowns while editing files with long lines,
this may be due to line truncation, or to one of the enabled minor
modes, or to the current major mode. Try turning off line truncation
@@ -396,6 +400,9 @@ and the major mode with 'M-x so-long-mode', or visit the file with
Note that the display optimizations in these cases may cause the
buffer to be occasionally mis-fontified.
+The new function 'long-line-optimizations-p' returns non-nil when
+these optimizations are in effect in the current buffer.
+
+++
** New command to change the font size globally.
To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to
@@ -454,7 +461,7 @@ duplicated on its right-hand side.
+++
** 'network-lookup-address-info' can now check numeric IP address validity.
-Specifying 'numeric as the new optional 'hints' argument makes it
+Specifying 'numeric' as the new optional 'hints' argument makes it
check if the passed address is a valid IPv4/IPv6 address (without DNS
traffic).
@@ -1250,6 +1257,12 @@ be used as a file-local variable.
If given a prefix, it will query the user for an argument to use for
the run/continue command.
+---
+*** 'perldb' now recognizes '-E'.
+As of Perl 5.10, 'perl -E 0' behaves like 'perl -e 0' but also activates
+all optional features of the Perl version in use. 'perldb' now uses
+this invocation as its default.
+
** Customize
---
@@ -1265,7 +1278,6 @@ Sets the value of the buffer-local variable 'whitespace-style' in
'diff-mode' buffers. By default, this variable is '(face trailing)',
which preserves behavior from previous Emacs versions.
-
** Ispell
---
@@ -1339,6 +1351,13 @@ When invoked with a non-zero prefix argument, as in 'C-u C-x C-e',
this command will pop up a new buffer and show the full pretty-printed
value there.
++++
+*** You can now generate a backtrace from Lisp errors in redisplay.
+To do this, set the new variable 'backtrace-on-redisplay-error' to a
+non-nil value. The backtrace will be written to a special buffer
+named "*Redisplay-trace*". This buffer will not be automatically
+displayed in a window.
+
** Compile
+++
@@ -1741,11 +1760,6 @@ The new ':doc-spec-function' element can be used to compute the
':doc-spec' element when the user asks for info on that particular
mode (instead of at load time).
-** Subr-x
-
-+++
-*** New macro 'with-memoization' provides a very primitive form of memoization.
-
** Ansi-color
---
@@ -2035,7 +2049,7 @@ This command displays a buffer containing the page load history of
the current WebKit widget, and allows you to navigate it.
---
-*** On X11, the WebKit inspector is now available inside xwidgets.
+*** On X, the WebKit inspector is now available inside xwidgets.
To access the inspector, right click on the widget and select "Inspect
Element".
@@ -2149,6 +2163,13 @@ Additionally, globs ending with '**/' or '***/' no longer raise an
error, and now expand to all directories recursively (following
symlinks in the latter case).
++++
+*** Lisp forms in Eshell now treat a 'nil' result as a failed exit status.
+When executing a command that looks like '(lisp form)', Eshell will
+set the exit status (available in the '$?' variable) to 2. This
+allows commands like that to be used as conditionals. To change this
+behavior, customize the new 'eshell-lisp-form-nil-is-failure' option.
+
** Shell
---
@@ -2229,10 +2250,10 @@ instead of also trying to ping it. Customize the user option
To respect Emacs naming conventions, the variable 'unread-bib-file'
has been renamed to 'bib-unread-file'. The following commands have
also been renamed:
- 'addbib' to 'bib-add'
- 'return-key-bib' to 'bib-return-key'
- 'mark-bib' to 'bib-mark'
- 'unread-bib' to 'bib-unread'
+ 'addbib' to 'bib-add'
+ 'return-key-bib' to 'bib-return-key'
+ 'mark-bib' to 'bib-mark'
+ 'unread-bib' to 'bib-unread'
---
*** proced.el shows system processes of remote hosts.
@@ -2551,6 +2572,18 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el.
* Lisp Changes in Emacs 29.1
+++
+** New function 'compiled-function-p'.
+This returns non-nil if its argument is either a built-in, or a
+byte-compiled, or a natively-compiled function object, or a function
+loaded from a dynamic module.
+
+---
+** 'deactivate-mark' can have new value 'dont-save'.
+This value means that Emacs should deactivate the mark as usual, but
+without setting the primary selection, if 'select-active-regions' is
+enabled.
+
++++
** New 'declare' form 'interactive-args'.
This can be used to specify what forms to put into 'command-history'
when executing commands interactively.
@@ -2562,8 +2595,8 @@ compiler now emits a warning about this deprecated usage.
+++
** Emacs now supports user-customizable and themable icons.
-These can be used for buttons in buffers and the like. See
-'(elisp)Icons' and '(emacs)Icons' for details.
+These can be used for buttons in buffers and the like. See the
+"(elisp) Icons" and "(emacs) Icons" nodes in the manuals for details.
+++
** New arguments MESSAGE and TIMEOUT of 'set-transient-map'.
@@ -2624,11 +2657,13 @@ things to be saved.
** New function 'string-equal-ignore-case'.
This compares strings ignoring case differences.
----
-** 'symbol-file' can now report natively-compiled .eln files.
+** 'symbol-file' can now report natively-compiled ".eln" files.
If Emacs was built with native-compilation enabled, Lisp programs can
now call 'symbol-file' with the new optional 3rd argument non-nil to
-request the name of the .eln file which defined a given symbol.
+request the name of the ".eln" file which defined a given symbol.
+
++++
+** New macro 'with-memoization' provides a very primitive form of memoization.
** Themes
@@ -2860,7 +2895,7 @@ This is like 'get-text-property', but works on the 'display' text
property.
+++
-** New function 'add-text-display-property'.
+** New function 'add-display-text-property'.
This is like 'put-text-property', but works on the 'display' text
property.
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 98c8d0c3026..6624f747c87 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -3435,14 +3435,6 @@ The fix is to install a newer version of ncurses, such as version 4.2.
Bootstrapping (compiling the .el files) is normally only necessary
with development builds, since the .elc files are pre-compiled in releases.
-*** "No rule to make target" with Ubuntu 8.04 make 3.81-3build1
-
-Compiling the lisp files fails at random places, complaining:
-"No rule to make target '/path/to/some/lisp.elc'".
-The causes of this problem are not understood. Using GNU make 3.81 compiled
-from source, rather than the Ubuntu version, worked.
-See <URL:https://debbugs.gnu.org/327>, <URL:https://debbugs.gnu.org/821>.
-
** Dumping
*** Segfault during 'make'
@@ -3567,6 +3559,15 @@ This section covers bugs reported on very old hardware or software.
If you are using hardware and an operating system shipped after 2000,
it is unlikely you will see any of these.
+** GNU/Linux
+
+*** Ubuntu 8.04 make 3.81-3build1: "No rule to make target"
+Compiling the lisp files fails at random places, complaining:
+"No rule to make target '/path/to/some/lisp.elc'".
+The causes of this problem are not understood. Using GNU make 3.81 compiled
+from source, rather than the Ubuntu version, worked.
+See <URL:https://debbugs.gnu.org/327>, <URL:https://debbugs.gnu.org/821>.
+
** Solaris
*** Problem with remote X server on Suns.
diff --git a/lisp/array.el b/lisp/array.el
index 08c5ff45ddd..aed93ffb65b 100644
--- a/lisp/array.el
+++ b/lisp/array.el
@@ -103,7 +103,7 @@ Set them to the optional arguments A-ROW and A-COLUMN if those are supplied."
(defun array-update-buffer-position ()
"Set `array-buffer-line' and `array-buffer-column' to their current values."
- (setq array-buffer-line (current-line)
+ (setq array-buffer-line (array-current-line)
array-buffer-column (current-column)))
@@ -113,7 +113,7 @@ Set them to the optional arguments A-ROW and A-COLUMN if those are supplied."
(defun array-what-position ()
"Display the row and column in which the cursor is positioned."
(interactive)
- (let ((array-buffer-line (current-line))
+ (let ((array-buffer-line (array-current-line))
(array-buffer-column (current-column)))
(message "Array row: %s Array column: %s"
(prin1-to-string (array-current-row))
@@ -147,13 +147,13 @@ Set them to the optional arguments A-ROW and A-COLUMN if those are supplied."
;;; Internal movement functions.
(defun array-beginning-of-field (&optional go-there)
- "Return the column of the beginning of the current field.
+ "Return the column of the beginning of the current field.
Optional argument GO-THERE, if non-nil, means go there too."
- ;; Requires that array-buffer-column be current.
- (let ((goal-column (- array-buffer-column (% array-buffer-column array-field-width))))
- (if go-there
- (move-to-column-untabify goal-column)
- goal-column)))
+ ;; Requires that array-buffer-column be current.
+ (let ((goal-column (- array-buffer-column (% array-buffer-column array-field-width))))
+ (if go-there
+ (array-move-to-column-untabify goal-column)
+ goal-column)))
(defun array-end-of-field (&optional go-there)
"Return the column of the end of the current array field.
@@ -162,7 +162,7 @@ If optional argument GO-THERE is non-nil, go there too."
(let ((goal-column (+ (- array-buffer-column (% array-buffer-column array-field-width))
array-field-width)))
(if go-there
- (move-to-column-untabify goal-column)
+ (array-move-to-column-untabify goal-column)
goal-column)))
(defun array-move-to-cell (a-row a-column)
@@ -174,7 +174,7 @@ Leave point at the beginning of the field and return the new buffer column."
(goal-column (* array-field-width (% (1- a-column) array-columns-per-line))))
(goto-char (point-min))
(forward-line goal-line)
- (move-to-column-untabify goal-column)))
+ (array-move-to-column-untabify goal-column)))
(defun array-move-to-row (a-row)
"Move to array row A-ROW preserving the current array column.
@@ -184,7 +184,7 @@ Leave point at the beginning of the field and return the new array row."
(% array-buffer-line array-lines-per-row)))
(goal-column (- array-buffer-column (% array-buffer-column array-field-width))))
(forward-line (- goal-line array-buffer-line))
- (move-to-column-untabify goal-column)
+ (array-move-to-column-untabify goal-column)
a-row))
(defun array-move-to-column (a-column)
@@ -196,7 +196,7 @@ Leave point at the beginning of the field and return the new array column."
(floor (1- a-column) array-columns-per-line)))
(goal-column (* array-field-width (% (1- a-column) array-columns-per-line))))
(forward-line (- goal-line array-buffer-line))
- (move-to-column-untabify goal-column)
+ (array-move-to-column-untabify goal-column)
a-column))
(defun array-move-one-row (sign)
@@ -214,7 +214,7 @@ If requested to move beyond the array bounds, signal an error."
(t
(progn
(forward-line (* sign array-lines-per-row))
- (move-to-column-untabify goal-column)
+ (array-move-to-column-untabify goal-column)
(+ array-row sign))))))
(defun array-move-one-column (sign)
@@ -233,15 +233,15 @@ If requested to move beyond the array bounds, signal an error."
;; Going backward from first column on the line.
((and (= sign -1) (= 1 (% array-column array-columns-per-line)))
(forward-line -1)
- (move-to-column-untabify
+ (array-move-to-column-untabify
(* array-field-width (1- array-columns-per-line))))
;; Going forward from last column on the line.
((and (= sign 1) (zerop (% array-column array-columns-per-line)))
(forward-line 1))
;; Somewhere in the middle of the line.
(t
- (move-to-column-untabify (+ (array-beginning-of-field)
- (* array-field-width sign)))))
+ (array-move-to-column-untabify (+ (array-beginning-of-field)
+ (* array-field-width sign)))))
(+ array-column sign)))))
(defun array-normalize-cursor ()
@@ -281,15 +281,15 @@ If necessary, scroll horizontally to keep the cursor in view."
"Move down one array row, staying in the current array column.
If optional ARG is given, move down ARG array rows."
(interactive "p")
- (let ((array-buffer-line (current-line))
+ (let ((array-buffer-line (array-current-line))
(array-buffer-column (current-column)))
(if (= (abs arg) 1)
(array-move-one-row arg)
(array-move-to-row
- (limit-index (+ (or (array-current-row)
- (error "Cursor is not in an array cell"))
- arg)
- array-max-row))))
+ (array--limit-index (+ (or (array-current-row)
+ (error "Cursor is not in an array cell"))
+ arg)
+ array-max-row))))
(array-normalize-cursor))
(defun array-previous-row (&optional arg)
@@ -303,15 +303,15 @@ If optional ARG is given, move up ARG array rows."
If optional ARG is given, move forward ARG array columns.
If necessary, keep the cursor in the window by scrolling right or left."
(interactive "p")
- (let ((array-buffer-line (current-line))
+ (let ((array-buffer-line (array-current-line))
(array-buffer-column (current-column)))
(if (= (abs arg) 1)
(array-move-one-column arg)
(array-move-to-column
- (limit-index (+ (or (array-current-column)
- (error "Cursor is not in an array cell"))
- arg)
- array-max-column))))
+ (array--limit-index (+ (or (array-current-column)
+ (error "Cursor is not in an array cell"))
+ arg)
+ array-max-column))))
(array-normalize-cursor))
(defun array-backward-column (&optional arg)
@@ -325,8 +325,8 @@ If necessary, keep the cursor in the window by scrolling right or left."
"Go to array row A-ROW and array column A-COLUMN."
(interactive "nArray row: \nnArray column: ")
(array-move-to-cell
- (limit-index a-row array-max-row)
- (limit-index a-column array-max-column))
+ (array--limit-index a-row array-max-row)
+ (array--limit-index a-column array-max-column))
(array-normalize-cursor))
@@ -417,7 +417,7 @@ Leave point at the beginning of the field."
"Copy the current field one array row down.
If optional ARG is given, copy down through ARG array rows."
(interactive "p")
- (let* ((array-buffer-line (current-line))
+ (let* ((array-buffer-line (array-current-line))
(array-buffer-column (current-column))
(array-row (or (array-current-row)
(error "Cursor is not in a valid array cell")))
@@ -425,7 +425,7 @@ If optional ARG is given, copy down through ARG array rows."
(if (= (abs arg) 1)
(array-copy-once-vertically arg)
(array-copy-to-row
- (limit-index (+ array-row arg) array-max-row))))
+ (array--limit-index (+ array-row arg) array-max-row))))
(array-normalize-cursor))
(defun array-copy-up (&optional arg)
@@ -438,7 +438,7 @@ If optional ARG is given, copy up through ARG array rows."
"Copy the current field one array column to the right.
If optional ARG is given, copy through ARG array columns to the right."
(interactive "p")
- (let* ((array-buffer-line (current-line))
+ (let* ((array-buffer-line (array-current-line))
(array-buffer-column (current-column))
(array-column (or (array-current-column)
(error "Cursor is not in a valid array cell")))
@@ -446,7 +446,7 @@ If optional ARG is given, copy through ARG array columns to the right."
(if (= (abs arg) 1)
(array-copy-once-horizontally arg)
(array-copy-to-column
- (limit-index (+ array-column arg) array-max-column))))
+ (array--limit-index (+ array-column arg) array-max-column))))
(array-normalize-cursor))
(defun array-copy-backward (&optional arg)
@@ -473,7 +473,7 @@ If optional ARG is given, copy through ARG array columns to the right."
(if (= (abs arg) 1)
(array-copy-once-horizontally arg)
(array-copy-to-column
- (limit-index (+ array-column arg) array-max-column))))))
+ (array--limit-index (+ array-column arg) array-max-column))))))
(message "Working...done")
(array-move-to-row array-row)
(array-normalize-cursor))
@@ -506,7 +506,7 @@ If optional ARG is given, copy through ARG rows down."
(forward-line 1)
(point))))
(this-row array-row)
- (goal-row (limit-index (+ this-row arg) array-max-row))
+ (goal-row (array--limit-index (+ this-row arg) array-max-row))
(num (- goal-row this-row))
(count (abs num))
(sign (if (not (zerop count)) (/ num count))))
@@ -700,13 +700,13 @@ of `array-rows-numbered'."
(floor (1- temp-max-column) new-columns-per-line))
(newlines-added 0))
(while (< newlines-removed newlines-to-be-removed)
- (move-to-column-untabify
+ (array-move-to-column-untabify
(* (1+ newlines-removed) old-line-length))
(kill-line 1)
(setq newlines-removed (1+ newlines-removed)))
(beginning-of-line)
(while (< newlines-added newlines-to-be-added)
- (move-to-column-untabify (* old-field-width new-columns-per-line))
+ (array-move-to-column-untabify (* old-field-width new-columns-per-line))
(newline)
(setq newlines-added (1+ newlines-added)))
(forward-line 1))))
@@ -735,16 +735,16 @@ of `array-rows-numbered'."
;;; Utilities.
-(defun limit-index (index limit)
+(defun array--limit-index (index limit)
(cond ((< index 1) 1)
((> index limit) limit)
(t index)))
-(defun current-line ()
+(defun array-current-line ()
"Return the current buffer line at point. The first line is 0."
(count-lines (point-min) (line-beginning-position)))
-(defun move-to-column-untabify (column)
+(defun array-move-to-column-untabify (column)
"Move to COLUMN on the current line, untabifying if necessary.
Return COLUMN."
(or (and (= column (move-to-column column))
@@ -753,10 +753,10 @@ Return COLUMN."
(if array-respect-tabs
(error "There is a TAB character in the way")
(progn
- (untabify-backward)
+ (array--untabify-backward)
(move-to-column column)))))
-(defun untabify-backward ()
+(defun array--untabify-backward ()
"Untabify the preceding TAB."
(save-excursion
(let ((start (point)))
@@ -885,7 +885,10 @@ Entering array mode calls the function `array-mode-hook'."
(setq-local truncate-lines t)
(setq overwrite-mode 'overwrite-mode-textual))
-
+(define-obsolete-function-alias 'limit-index #'array--limit-index "29.1")
+(define-obsolete-function-alias 'current-line #'array-current-line "29.1")
+(define-obsolete-function-alias 'move-to-column-untabify #'array-move-to-column-untabify "29.1")
+(define-obsolete-function-alias 'untabify-backward #'array--untabify-backward "29.1")
(provide 'array)
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index 30a03e0431e..d0893e932b4 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -966,7 +966,7 @@ it removes only the first instance of a bookmark with that name from
the list of bookmarks.)"
(interactive (list nil current-prefix-arg))
(let ((prompt
- (if no-overwrite "Append bookmark named" "Set bookmark named")))
+ (if no-overwrite "Add bookmark named" "Set bookmark named")))
(bookmark-set-internal prompt name (if no-overwrite 'push 'overwrite))))
;;;###autoload
diff --git a/lisp/calc/calc-vec.el b/lisp/calc/calc-vec.el
index 3b8629b797d..8d99f62a9ba 100644
--- a/lisp/calc/calc-vec.el
+++ b/lisp/calc/calc-vec.el
@@ -647,9 +647,7 @@
(defun calcFunc-rhead (vec)
(if (and (Math-vectorp vec)
(cdr vec))
- (let ((vec (copy-sequence vec)))
- (setcdr (nthcdr (- (length vec) 2) vec) nil)
- vec)
+ (butlast vec)
(calc-record-why 'vectorp vec)
(list 'calcFunc-rhead vec)))
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 254c703ee22..6c21430b1b3 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -1959,12 +1959,8 @@ See calc-keypad for details."
(or n (setq n 1))
(or m (setq m 1))
(calc-check-stack (+ n m -1))
- (and (> n 0)
- (let ((top (copy-sequence (nthcdr (+ m calc-stack-top -1)
- calc-stack))))
- (setcdr (nthcdr (1- n) top) nil)
- (nreverse
- (mapcar (lambda (x) (calc-get-stack-element x sel-mode)) top)))))
+ (nreverse (mapcar (lambda (x) (calc-get-stack-element x sel-mode))
+ (take n (nthcdr (+ m calc-stack-top -1) calc-stack)))))
(defun calc-top-list-n (&optional n m sel-mode)
(mapcar #'math-check-complete
@@ -2291,9 +2287,7 @@ the United States."
((and (null n)
(eq (car-safe top) 'incomplete)
(> (length top) (if (eq (nth 1 top) 'intv) 3 2)))
- (calc-pop-push-list 1 (let ((tt (copy-sequence top)))
- (setcdr (nthcdr (- (length tt) 2) tt) nil)
- (list tt))))
+ (calc-pop-push-list 1 (list (butlast top))))
((< nn 0)
(if (and calc-any-selections
(calc-top-selected 1 (- nn)))
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 7e911d814dc..bbdcaa4db4e 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -171,13 +171,13 @@ If DATE lacks timezone information, GMT is assumed."
(error "Invalid date: %s" date)))))))))
;;;###autoload
-(defalias 'time-to-seconds 'float-time)
+(defalias 'time-to-seconds #'float-time)
;;;###autoload
-(defun seconds-to-time (seconds &rest form)
- "Convert SECONDS to a proper time, like `current-time' would.
-FORM means the same as in `time-convert'."
- (time-convert seconds form))
+(defun seconds-to-time (seconds)
+ "Convert SECONDS to a proper time, like `current-time' would."
+ ;; FIXME: Should we (declare (obsolete time-convert "27.1")) ?
+ (time-convert seconds 'list))
;;;###autoload
(defun days-to-time (days)
@@ -202,7 +202,7 @@ TIME should be either a time value or a date-time string."
(time-subtract nil time))
;;;###autoload
-(define-obsolete-function-alias 'subtract-time 'time-subtract "26.1")
+(define-obsolete-function-alias 'subtract-time #'time-subtract "26.1")
;;;###autoload
(defun date-to-day (date)
diff --git a/lisp/cedet/cedet.el b/lisp/cedet/cedet.el
index e6befb10e91..c33ac850722 100644
--- a/lisp/cedet/cedet.el
+++ b/lisp/cedet/cedet.el
@@ -25,15 +25,12 @@
;;; Commentary:
;;; Code:
-;;
-;; This file depends on the major components of CEDET, so that you can
-;; load them all by doing (require 'cedet). This is mostly for
-;; compatibility with the upstream, stand-alone CEDET distribution.
(declare-function inversion-find-version "inversion")
(defconst cedet-version "2.0"
"Current version of CEDET.")
+(make-obsolete-variable 'cedet-version 'emacs-version "29.1")
(defconst cedet-packages
`(
@@ -45,6 +42,7 @@
(ede "1.2" nil "ede" )
)
"Table of CEDET packages to install.")
+(make-obsolete-variable 'cedet-packages 'package-built-in-p "29.1")
(defvar cedet-menu-map ;(make-sparse-keymap "CEDET menu")
(let ((map (make-sparse-keymap "CEDET menu")))
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index 4ea14e33c5d..e6bfd0b1e85 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -1,10 +1,10 @@
;;; ede.el --- Emacs Development Environment gloss -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2005, 2007-2022 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2022 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
-;; Version: 1.2
+;; Version: 2.0
;; This file is part of GNU Emacs.
@@ -39,6 +39,8 @@
;;
;; (global-ede-mode t)
+;;; Code:
+
(require 'cedet)
(require 'cl-lib)
(require 'eieio)
@@ -66,10 +68,11 @@
(defconst ede-version "2.0"
"Current version of the Emacs EDE.")
+(make-obsolete-variable 'ede-version 'emacs-version "29.1")
-;;; Code:
(defun ede-version ()
"Display the current running version of EDE."
+ (declare (obsolete emacs-version "29.1"))
(interactive) (message "EDE %s" ede-version))
(defgroup ede nil
diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el
index cbe766cedb6..c83e6873679 100644
--- a/lisp/cedet/ede/emacs.el
+++ b/lisp/cedet/ede/emacs.el
@@ -80,7 +80,6 @@ ROOTPROJ is nil, since there is only one project."
;; Doesn't already exist, so let's make one.
(let* ((vertuple (ede-emacs-version dir)))
(ede-emacs-project
- (car vertuple)
:name (car vertuple)
:version (cdr vertuple)
:directory (file-name-as-directory dir)
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index 78002dd8abc..3166279de40 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -34,6 +34,8 @@
;; menu). To enable it at startup, put (semantic-mode 1) in your init
;; file.
+;;; Code:
+
(require 'cedet)
(require 'semantic/tag)
(require 'semantic/lex)
@@ -41,6 +43,7 @@
(defvar semantic-version "2.2"
"Current version of Semantic.")
+(make-obsolete-variable 'semantic-version 'emacs-version "29.1")
(declare-function inversion-test "inversion")
(declare-function semanticdb-load-ebrowse-caches "semantic/db-ebrowse")
@@ -73,9 +76,6 @@ introduced."
(require 'semantic/fw)
-;;; Code:
-;;
-
;;; Variables and Configuration
;;
(defvar-local semantic--parse-table nil
diff --git a/lisp/cedet/semantic/bovine.el b/lisp/cedet/semantic/bovine.el
index 1e52b1f8504..a6cf8d89a4f 100644
--- a/lisp/cedet/semantic/bovine.el
+++ b/lisp/cedet/semantic/bovine.el
@@ -143,14 +143,14 @@ list of semantic tokens found."
cvl nil ;re-init the collected value list.
lte (car matchlist) ;Get the local matchlist entry.
)
- (if (or (byte-code-function-p (car lte))
+ (if (or (compiled-function-p (car lte))
(listp (car lte)))
;; In this case, we have an EMPTY match! Make
;; stuff up.
(setq cvl (list nil))))
(while (and lte
- (not (byte-code-function-p (car lte)))
+ (not (compiled-function-p (car lte)))
(not (listp (car lte))))
;; GRAMMAR SOURCE DEBUGGING!
diff --git a/lisp/cedet/semantic/db-file.el b/lisp/cedet/semantic/db-file.el
index d00ab47ce69..e2c9d618ba2 100644
--- a/lisp/cedet/semantic/db-file.el
+++ b/lisp/cedet/semantic/db-file.el
@@ -29,7 +29,7 @@
(require 'cedet-files)
(require 'data-debug)
-(defvar semanticdb-file-version semantic-version
+(defvar semanticdb-file-version "2.2"
"Version of semanticdb we are writing files to disk with.")
(defvar semanticdb-file-incompatible-version "1.4"
"Version of semanticdb we are not reverse compatible with.")
diff --git a/lisp/cedet/semantic/wisent/comp.el b/lisp/cedet/semantic/wisent/comp.el
index 17cd3b1d59a..e24f6128a68 100644
--- a/lisp/cedet/semantic/wisent/comp.el
+++ b/lisp/cedet/semantic/wisent/comp.el
@@ -38,7 +38,7 @@
;;; Code:
(require 'semantic/wisent)
(eval-when-compile (require 'cl-lib))
-(eval-when-compile (require 'subr-x)) ; `string-pad'
+(require 'subr-x) ; `string-pad'
;;;; -------------------
;;;; Misc. useful things
diff --git a/lisp/cedet/srecode.el b/lisp/cedet/srecode.el
index 7c054d4c100..9691f906a4c 100644
--- a/lisp/cedet/srecode.el
+++ b/lisp/cedet/srecode.el
@@ -37,14 +37,16 @@
;;
;; See the srecode manual for specific details.
+;;; Code:
+
(require 'eieio)
(require 'mode-local)
(load "srecode/loaddefs" nil 'nomessage)
(defvar srecode-version "1.2"
"Current version of the Semantic Recoder.")
+(make-obsolete-variable 'srecode-version 'emacs-version "29.1")
-;;; Code:
(defgroup srecode nil
"Semantic Recoder."
:group 'extensions
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index 16971aa6611..7fad031add6 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -655,7 +655,9 @@ The character information includes:
("file code"
,@(if multibyte-p
(let* ((coding buffer-file-coding-system)
- (encoded (encode-coding-char char coding charset)))
+ (encoded
+ (and coding
+ (encode-coding-char char coding charset))))
(if encoded
(list (encoded-string-description encoded coding)
(format "(encoded by coding system %S)"
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el
index 2a2bcca7007..d383650f4e5 100644
--- a/lisp/emacs-lisp/advice.el
+++ b/lisp/emacs-lisp/advice.el
@@ -1054,9 +1054,9 @@
;; (print "Let's clean up now!"))
;; foo
;;
-;; Now `foo's advice is byte-compiled:
+;; Now `foo's advice is compiled:
;;
-;; (byte-code-function-p 'ad-Advice-foo)
+;; (compiled-function-p 'ad-Advice-foo)
;; t
;;
;; (foo 3)
@@ -1298,7 +1298,7 @@
;; constructed during preactivation was used, even though we did not specify
;; the `compile' flag:
;;
-;; (byte-code-function-p 'ad-Advice-fum)
+;; (compiled-function-p 'ad-Advice-fum)
;; t
;;
;; (fum 2)
@@ -1329,7 +1329,7 @@
;;
;; A new uncompiled advised definition got constructed:
;;
-;; (byte-code-function-p 'ad-Advice-fum)
+;; (compiled-function-p 'ad-Advice-fum)
;; nil
;;
;; (fum 2)
@@ -1580,8 +1580,6 @@
:link '(custom-manual "(elisp)Advising Functions")
:group 'lisp)
-(defconst ad-version "2.14")
-
;;;###autoload
(defcustom ad-redefinition-action 'warn
"Defines what to do with redefinitions during Advice de/activation.
@@ -2118,9 +2116,9 @@ the cache-id will clear the cache."
(defsubst ad-compiled-p (definition)
"Return non-nil if DEFINITION is a compiled byte-code object."
- (or (byte-code-function-p definition)
- (and (macrop definition)
- (byte-code-function-p (ad-lambdafy definition)))))
+ (or (compiled-function-p definition)
+ (and (macrop definition)
+ (compiled-function-p (ad-lambdafy definition)))))
(defsubst ad-compiled-code (compiled-definition)
"Return the byte-code object of a COMPILED-DEFINITION."
@@ -3250,6 +3248,9 @@ Use only in REAL emergencies."
(message "Oops! Left over advised function %S" function)
(ad-pop-advised-function function)))
+(defconst ad-version "2.14")
+(make-obsolete-variable 'ad-version 'emacs-version "29.1")
+
(provide 'advice)
;;; advice.el ends here
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 7a4bbf2e8af..52e00952846 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1207,25 +1207,26 @@ See Info node `(elisp) Integer Basics'."
form)))
(defun byte-optimize-apply (form)
- ;; If the last arg is a literal constant, turn this into a funcall.
- ;; The funcall optimizer can then transform (funcall 'foo ...) -> (foo ...).
- (if (= (length form) 2)
- ;; single-argument `apply' is not worth optimizing (bug#40968)
- form
- (let ((fn (nth 1 form))
- (last (nth (1- (length form)) form))) ; I think this really is fastest
- (or (if (or (null last)
- (eq (car-safe last) 'quote))
- (if (listp (nth 1 last))
- (let ((butlast (nreverse (cdr (reverse (cdr (cdr form)))))))
- (nconc (list 'funcall fn) butlast
- (mapcar (lambda (x) (list 'quote x)) (nth 1 last))))
+ (let ((len (length form)))
+ (if (>= len 2)
+ (let ((fn (nth 1 form))
+ (last (nth (1- len) form)))
+ (cond
+ ;; (apply F ... '(X Y ...)) -> (funcall F ... 'X 'Y ...)
+ ((or (null last)
+ (eq (car-safe last) 'quote))
+ (let ((last-value (nth 1 last)))
+ (if (listp last-value)
+ `(funcall ,fn ,@(butlast (cddr form))
+ ,@(mapcar (lambda (x) (list 'quote x)) last-value))
(byte-compile-warn-x
- last
- "last arg to apply can't be a literal atom: `%s'"
- last)
- nil))
- form))))
+ last "last arg to apply can't be a literal atom: `%s'" last)
+ nil)))
+ ;; (apply F ... (list X Y ...)) -> (funcall F ... X Y ...)
+ ((eq (car-safe last) 'list)
+ `(funcall ,fn ,@(butlast (cddr form)) ,@(cdr last)))
+ (t form)))
+ form)))
(put 'funcall 'byte-optimizer #'byte-optimize-funcall)
(put 'apply 'byte-optimizer #'byte-optimize-apply)
@@ -1747,10 +1748,10 @@ See Info node `(elisp) Integer Basics'."
byte-goto-if-not-nil-else-pop))
(defconst byte-after-unbind-ops
- '(byte-constant byte-dup
+ '(byte-constant byte-dup byte-stack-ref byte-stack-set byte-discard
byte-symbolp byte-consp byte-stringp byte-listp byte-numberp byte-integerp
byte-eq byte-not
- byte-cons byte-list1 byte-list2 ; byte-list3 byte-list4
+ byte-cons byte-list1 byte-list2 byte-list3 byte-list4 byte-listN
byte-interactive-p)
;; How about other side-effect-free-ops? Is it safe to move an
;; error invocation (such as from nth) out of an unwind-protect?
@@ -1762,7 +1763,8 @@ See Info node `(elisp) Integer Basics'."
(defconst byte-compile-side-effect-and-error-free-ops
'(byte-constant byte-dup byte-symbolp byte-consp byte-stringp byte-listp
byte-integerp byte-numberp byte-eq byte-equal byte-not byte-car-safe
- byte-cdr-safe byte-cons byte-list1 byte-list2 byte-point byte-point-max
+ byte-cdr-safe byte-cons byte-list1 byte-list2 byte-list3 byte-list4
+ byte-listN byte-point byte-point-max
byte-point-min byte-following-char byte-preceding-char
byte-current-column byte-eolp byte-eobp byte-bolp byte-bobp
byte-current-buffer byte-stack-ref))
@@ -2113,13 +2115,15 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
(setcar (cdr rest) lap0)
(setq keep-going t))
;;
- ;; varbind-X unbind-N --> discard unbind-(N-1)
- ;; save-excursion unbind-N --> unbind-(N-1)
- ;; save-restriction unbind-N --> unbind-(N-1)
+ ;; varbind-X unbind-N --> discard unbind-(N-1)
+ ;; save-excursion unbind-N --> unbind-(N-1)
+ ;; save-restriction unbind-N --> unbind-(N-1)
+ ;; save-current-buffer unbind-N --> unbind-(N-1)
;;
((and (eq 'byte-unbind (car lap1))
(memq (car lap0) '(byte-varbind byte-save-excursion
- byte-save-restriction))
+ byte-save-restriction
+ byte-save-current-buffer))
(< 0 (cdr lap1)))
(if (zerop (setcdr lap1 (1- (cdr lap1))))
(delq lap1 rest))
@@ -2475,8 +2479,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
;; itself, compile some of its most used recursive functions (at load time).
;;
(eval-when-compile
- (or (byte-code-function-p (symbol-function 'byte-optimize-form))
- (subr-native-elisp-p (symbol-function 'byte-optimize-form))
+ (or (compiled-function-p (symbol-function 'byte-optimize-form))
(assq 'byte-code (symbol-function 'byte-optimize-form))
(let ((byte-optimize nil)
(byte-compile-warnings nil))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 9d5f6682b5a..907015eb48e 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1395,7 +1395,7 @@ when printing the error message."
(or (symbolp (symbol-function fn))
(consp (symbol-function fn))
(and (not macro-p)
- (byte-code-function-p (symbol-function fn)))))
+ (compiled-function-p (symbol-function fn)))))
(setq fn (symbol-function fn)))
(let ((advertised (gethash (if (and (symbolp fn) (fboundp fn))
;; Could be a subr.
@@ -1407,7 +1407,7 @@ when printing the error message."
(if macro-p
`(macro lambda ,advertised)
`(lambda ,advertised)))
- ((and (not macro-p) (byte-code-function-p fn)) fn)
+ ((and (not macro-p) (compiled-function-p fn)) fn)
((not (consp fn)) nil)
((eq 'macro (car fn)) (cdr fn))
(macro-p nil)
@@ -2946,11 +2946,11 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(setq fun (cdr fun)))
(prog1
(cond
- ;; Up until Emacs-24.1, byte-compile silently did nothing when asked to
- ;; compile something invalid. So let's tune down the complaint from an
- ;; error to a simple message for the known case where signaling an error
- ;; causes problems.
- ((byte-code-function-p fun)
+ ;; Up until Emacs-24.1, byte-compile silently did nothing
+ ;; when asked to compile something invalid. So let's tone
+ ;; down the complaint from an error to a simple message for
+ ;; the known case where signaling an error causes problems.
+ ((compiled-function-p fun)
(message "Function %s is already compiled"
(if (symbolp form) form "provided"))
fun)
@@ -3527,7 +3527,7 @@ lambda-expression."
(byte-compile-out-tag endtag)))
(defun byte-compile-unfold-bcf (form)
- "Inline call to byte-code-functions."
+ "Inline call to byte-code function."
(let* ((byte-compile-bound-variables byte-compile-bound-variables)
(fun (car form))
(fargs (aref fun 0))
@@ -5254,11 +5254,13 @@ invoked interactively."
((not (consp f))
"<malformed function>")
((eq 'macro (car f))
- (if (or (byte-code-function-p (cdr f))
+ (if (or (compiled-function-p (cdr f))
+ ;; FIXME: Can this still happen?
(assq 'byte-code (cdr (cdr (cdr f)))))
" <compiled macro>"
" <macro>"))
((assq 'byte-code (cdr (cdr f)))
+ ;; FIXME: Can this still happen?
"<compiled lambda>")
((eq 'lambda (car f))
"<function>")
@@ -5507,9 +5509,7 @@ and corresponding effects."
;; itself, compile some of its most used recursive functions (at load time).
;;
(eval-when-compile
- (or (byte-code-function-p (symbol-function 'byte-compile-form))
- (subr-native-elisp-p (symbol-function 'byte-compile-form))
- (assq 'byte-code (symbol-function 'byte-compile-form))
+ (or (compiled-function-p (symbol-function 'byte-compile-form))
(let ((byte-optimize nil) ; do it fast
(byte-compile-warnings nil))
(mapc (lambda (x)
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index ac589b82f83..04ead562f2f 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-1998, 2001-2022 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2022 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Old-Version: 0.6.2
@@ -1357,23 +1357,6 @@ checking of documentation strings.
checkdoc-common-verbs-wrong-voice "\\|")
"\\)\\>"))))
-;; Profiler says this is not yet faster than just calling assoc
-;;(defun checkdoc-word-in-alist-vector (word vector)
-;; "Check to see if WORD is in the car of an element of VECTOR.
-;;VECTOR must be sorted. The CDR should be a replacement. Since the
-;;word list is getting bigger, it is time for a quick bisecting search."
-;; (let ((max (length vector)) (min 0) i
-;; (found nil) (fw nil))
-;; (setq i (/ max 2))
-;; (while (and (not found) (/= min max))
-;; (setq fw (car (aref vector i)))
-;; (cond ((string= word fw) (setq found (cdr (aref vector i))))
-;; ((string< word fw) (setq max i))
-;; (t (setq min i)))
-;; (setq i (/ (+ max min) 2))
-;; )
-;; found))
-
;;; Checking engines
;;
(defun checkdoc-this-string-valid (&optional take-notes)
@@ -2860,8 +2843,6 @@ function called to create the messages."
(custom-add-option 'emacs-lisp-mode-hook 'checkdoc-minor-mode)
-;; Obsolete
-
(define-obsolete-function-alias 'checkdoc-run-hooks
#'run-hook-with-args-until-success "28.1")
(defvar checkdoc-version "0.6.2"
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index eefaa36b911..80ca43c902a 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -3411,7 +3411,7 @@ Of course, we really can't know that for sure, so it's just a heuristic."
(character . natnump)
(char-table . char-table-p)
(command . commandp)
- (compiled-function . byte-code-function-p)
+ (compiled-function . compiled-function-p)
(hash-table . hash-table-p)
(cons . consp)
(fixnum . fixnump)
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index c8ff6b68144..047b0069bb9 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -1813,8 +1813,7 @@ Ran \\([0-9]+\\) tests, \\([0-9]+\\) results as expected\
(unless (or (null tests) (zerop high))
(message "\nLONG-RUNNING TESTS")
(message "------------------")
- (setq tests (sort tests (lambda (x y) (> (car x) (car y)))))
- (when (< high (length tests)) (setcdr (nthcdr (1- high) tests) nil))
+ (setq tests (ntake high (sort tests (lambda (x y) (> (car x) (car y))))))
(message "%s" (mapconcat #'cdr tests "\n")))
;; More details on hydra and emba, where the logs are harder to get to.
(when (and (or (getenv "EMACS_HYDRA_CI") (getenv "EMACS_EMBA_CI"))
diff --git a/lisp/emacs-lisp/helper.el b/lisp/emacs-lisp/helper.el
index 654dbbc5fef..10bb2973253 100644
--- a/lisp/emacs-lisp/helper.el
+++ b/lisp/emacs-lisp/helper.el
@@ -131,7 +131,6 @@
(defun Helper-describe-bindings ()
"Describe local key bindings of current mode."
(interactive)
- (message "Making binding list...")
(save-window-excursion (describe-bindings))
(Helper-help-scroller))
diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el
index 3b329357ad9..31e1514193f 100644
--- a/lisp/emacs-lisp/loaddefs-gen.el
+++ b/lisp/emacs-lisp/loaddefs-gen.el
@@ -519,15 +519,21 @@ binds `generated-autoload-file' as a file-local variable, write
its autoloads into the specified file instead.
The function does NOT recursively descend into subdirectories of the
-directory or directories specified.
+directory or directories specified by DIRS.
-If EXTRA-DATA, include this string at the start of the generated
-file. This will also force generation of OUTPUT-FILE even if
-there are no autoloads to put into the file.
+Optional argument EXCLUDED-FILES, if non-nil, should be a list of
+files, such as preloaded files, whose autoloads should not be written
+to OUTPUT-FILE.
-If INCLUDE-PACKAGE-VERSION, include package version data.
+If EXTRA-DATA is non-nil, it should be a string; include that string
+at the beginning of the generated file. This will also force the
+generation of OUTPUT-FILE even if there are no autoloads to put into
+that file.
-If GENERATE-FULL, don't update, but regenerate all the loaddefs files."
+If INCLUDE-PACKAGE-VERSION is non-nil, include package version data.
+
+If GENERATE-FULL is non-nil, regenerate all the loaddefs files anew,
+instead of just updating them with the new/changed autoloads."
(let* ((files-re (let ((tmp nil))
(dolist (suf (get-load-suffixes))
;; We don't use module-file-suffix below because
@@ -545,6 +551,11 @@ If GENERATE-FULL, don't update, but regenerate all the loaddefs files."
(updating (and (file-exists-p output-file) (not generate-full)))
(defs nil))
+ ;; Allow the excluded files to be relative.
+ (setq excluded-files
+ (mapcar (lambda (file) (expand-file-name file dir))
+ excluded-files))
+
;; Collect all the autoload data.
(let ((progress (make-progress-reporter
(byte-compile-info
@@ -583,7 +594,8 @@ If GENERATE-FULL, don't update, but regenerate all the loaddefs files."
;; We have some data, so generate the loaddef files. First
;; group per output file.
(dolist (fdefs (seq-group-by #'car defs))
- (let ((loaddefs-file (car fdefs)))
+ (let ((loaddefs-file (car fdefs))
+ hash)
(with-temp-buffer
(if (and updating (file-exists-p loaddefs-file))
(insert-file-contents loaddefs-file)
@@ -593,6 +605,7 @@ If GENERATE-FULL, don't update, but regenerate all the loaddefs files."
(when extra-data
(insert extra-data)
(ensure-empty-lines 1)))
+ (setq hash (buffer-hash))
;; Then group by source file (and sort alphabetically).
(dolist (section (sort (seq-group-by #'cadr (cdr fdefs))
(lambda (e1 e2)
@@ -629,9 +642,11 @@ If GENERATE-FULL, don't update, but regenerate all the loaddefs files."
(loaddefs-generate--print-form def))
(unless (bolp)
(insert "\n")))))
- (write-region (point-min) (point-max) loaddefs-file nil 'silent)
- (byte-compile-info (file-relative-name loaddefs-file lisp-directory)
- t "GEN")))))))
+ ;; Only write the file if we actually made a change.
+ (unless (equal (buffer-hash) hash)
+ (write-region (point-min) (point-max) loaddefs-file nil 'silent)
+ (byte-compile-info
+ (file-relative-name loaddefs-file lisp-directory) t "GEN"))))))))
(defun loaddefs-generate--print-form (def)
"Print DEF in a format that makes sense for version control."
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index 6a193a56d2d..5ae9d8368f0 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -823,7 +823,7 @@ test of free variables in the following ways:
(eval-when-compile
(add-hook 'emacs-startup-hook
(lambda ()
- (and (not (byte-code-function-p
+ (and (not (compiled-function-p
(symbol-function 'macroexpand-all)))
(locate-library "macroexp.elc")
(load "macroexp.elc")))))
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index 2d5a1b5e77b..a9a20ab5abf 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -167,31 +167,31 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are expected.")
(defun advice--interactive-form (function)
"Like `interactive-form' but tries to avoid autoloading functions."
- (when (commandp function)
- (if (not (and (symbolp function) (autoloadp (indirect-function function))))
- (interactive-form function)
+ (if (not (and (symbolp function) (autoloadp (indirect-function function))))
+ (interactive-form function)
+ (when (commandp function)
`(interactive (advice-eval-interactive-spec
(cadr (interactive-form ',function)))))))
-(defun advice--make-interactive-form (function main)
+(defun advice--make-interactive-form (iff ifm)
;; TODO: make it so that interactive spec can be a constant which
;; dynamically checks the advice--car/cdr to do its job.
;; For that, advice-eval-interactive-spec needs to be more faithful.
- (let* ((iff (advice--interactive-form function))
- (ifm (advice--interactive-form main))
- (fspec (cadr iff)))
+ (let* ((fspec (cadr iff)))
(when (eq 'function (car-safe fspec)) ;; Macroexpanded lambda?
- (setq fspec (nth 1 fspec)))
+ (setq fspec (eval fspec t)))
(if (functionp fspec)
`(funcall ',fspec ',(cadr ifm))
(cadr (or iff ifm)))))
(cl-defmethod oclosure-interactive-form ((ad advice) &optional _)
- (let ((car (advice--car ad))
- (cdr (advice--cdr ad)))
- (when (or (commandp car) (commandp cdr))
- `(interactive ,(advice--make-interactive-form car cdr)))))
+ (let* ((car (advice--car ad))
+ (cdr (advice--cdr ad))
+ (ifa (advice--interactive-form car))
+ (ifd (advice--interactive-form cdr)))
+ (when (or ifa ifd)
+ `(interactive ,(advice--make-interactive-form ifa ifd)))))
(cl-defmethod cl-print-object ((object advice) stream)
(cl-assert (advice--p object))
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index d2959f7728c..ed23ee5f221 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -3530,7 +3530,7 @@ If optional arg BUTTON is non-nil, describe its associated package."
(let ((place (cdr desc))
(out (copy-sequence (car desc))))
(add-text-properties place (1+ place)
- '(face (bold font-lock-warning-face))
+ '(face help-key-binding)
out)
out))
(package--prettify-quick-help-key (cons desc 0))))
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 07443dabfef..10bd4bc6886 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -607,31 +607,38 @@ recording whether the var has been referenced by earlier parts of the match."
(symbolp . vectorp)
(symbolp . stringp)
(symbolp . byte-code-function-p)
+ (symbolp . compiled-function-p)
(symbolp . recordp)
(integerp . consp)
(integerp . arrayp)
(integerp . vectorp)
(integerp . stringp)
(integerp . byte-code-function-p)
+ (integerp . compiled-function-p)
(integerp . recordp)
(numberp . consp)
(numberp . arrayp)
(numberp . vectorp)
(numberp . stringp)
(numberp . byte-code-function-p)
+ (numberp . compiled-function-p)
(numberp . recordp)
(consp . arrayp)
(consp . atom)
(consp . vectorp)
(consp . stringp)
(consp . byte-code-function-p)
+ (consp . compiled-function-p)
(consp . recordp)
(arrayp . byte-code-function-p)
+ (arrayp . compiled-function-p)
(vectorp . byte-code-function-p)
+ (vectorp . compiled-function-p)
(vectorp . recordp)
(stringp . vectorp)
(stringp . recordp)
- (stringp . byte-code-function-p)))
+ (stringp . byte-code-function-p)
+ (stringp . compiled-function-p)))
(defun pcase--mutually-exclusive-p (pred1 pred2)
(or (member (cons pred1 pred2)
@@ -771,8 +778,8 @@ A and B can be one of:
((consp (cadr pat)) #'consp)
((stringp (cadr pat)) #'stringp)
((vectorp (cadr pat)) #'vectorp)
- ((byte-code-function-p (cadr pat))
- #'byte-code-function-p))))
+ ((compiled-function-p (cadr pat))
+ #'compiled-function-p))))
(pcase--mutually-exclusive-p (cadr upat) otherpred))
'(:pcase--fail . nil))
;; Since we turn (or 'a 'b 'c) into (pred (pcase--flip (memq '(a b c))))
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
index 2b2039f9d15..e8b92a532fa 100644
--- a/lisp/emacs-lisp/ring.el
+++ b/lisp/emacs-lisp/ring.el
@@ -42,6 +42,8 @@
;;; Code:
+(eval-when-compile (require 'cl-lib))
+
;;; User Functions:
;;;###autoload
@@ -51,6 +53,8 @@
(consp (cdr x)) (integerp (cadr x))
(vectorp (cddr x))))
+(cl-deftype ring () '(satisfies ring-p))
+
;;;###autoload
(defun make-ring (size)
"Make a ring that can contain SIZE elements."
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 6ddd8de6e8d..b6f0f66e5b1 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -458,11 +458,21 @@ TESTFN is used to compare elements, or `equal' if TESTFN is nil."
(cl-defmethod seq-uniq ((sequence list) &optional testfn)
(let ((result nil))
(if (not testfn)
- ;; Fast path.
- (while sequence
- (unless (member (car sequence) result)
- (push (car sequence) result))
- (pop sequence))
+ ;; Fast path. If the list is long, use a hash table to speed
+ ;; things up even more.
+ (let ((l (length sequence)))
+ (if (> l 100)
+ (let ((hash (make-hash-table :test #'equal :size l)))
+ (while sequence
+ (unless (gethash (car sequence) hash)
+ (setf (gethash (car sequence) hash) t)
+ (push (car sequence) result))
+ (setq sequence (cdr sequence))))
+ ;; Short list.
+ (while sequence
+ (unless (member (car sequence) result)
+ (push (car sequence) result))
+ (pop sequence))))
;; Slower path.
(while sequence
(unless (seq-find (lambda (elem)
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index b7083bfe7cc..bd7c3c82f97 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -254,13 +254,9 @@ the string."
(unless (natnump length)
(signal 'wrong-type-argument (list 'natnump length)))
(let ((pad-length (- length (length string))))
- (if (< pad-length 0)
- string
- (concat (and start
- (make-string pad-length (or padding ?\s)))
- string
- (and (not start)
- (make-string pad-length (or padding ?\s)))))))
+ (cond ((<= pad-length 0) string)
+ (start (concat (make-string pad-length (or padding ?\s)) string))
+ (t (concat string (make-string pad-length (or padding ?\s)))))))
(defun string-chop-newline (string)
"Remove the final newline (if any) from STRING."
@@ -471,6 +467,18 @@ be marked unmodified, effectively ignoring those changes."
(equal ,hash (buffer-hash)))
(restore-buffer-modified-p nil))))))))
+(defun emacs-etc--hide-local-variables ()
+ "Hide local variables.
+Used by `emacs-authors-mode' and `emacs-news-mode'."
+ (narrow-to-region (point-min)
+ (save-excursion
+ (goto-char (point-max))
+ ;; Obfuscate to avoid this being interpreted
+ ;; as a local variable section itself.
+ (if (re-search-backward "^Local\sVariables:$" nil t)
+ (progn (forward-line -1) (point))
+ (point-max)))))
+
(provide 'subr-x)
;;; subr-x.el ends here
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index d1634c64ad3..d1c8b5ff2dd 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -7,7 +7,7 @@
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Keywords: emulations
-;; Version: 3.14.1
+;; Version: 3.14.2
;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
;; file on 20/3/2008, and the maintainer agreed that when a bug is
diff --git a/lisp/eshell/em-alias.el b/lisp/eshell/em-alias.el
index 5d3aaf7c81c..9ad218d5988 100644
--- a/lisp/eshell/em-alias.el
+++ b/lisp/eshell/em-alias.el
@@ -206,7 +206,7 @@ file named by `eshell-aliases-file'.")
(let ((eshell-current-handles
(eshell-create-handles eshell-aliases-file 'overwrite)))
(eshell/alias)
- (eshell-close-handles 0))))
+ (eshell-close-handles 0 'nil))))
(defsubst eshell-lookup-alias (name)
"Check whether NAME is aliased. Return the alias if there is one."
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 775e4c1057e..62c95056fd2 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -133,6 +133,10 @@ There are several different kinds of commands, however."
Such arguments will be passed to `read', and then evaluated."
:type 'regexp)
+(defcustom eshell-lisp-form-nil-is-failure t
+ "If non-nil, Lisp forms like (COMMAND ARGS) treat a nil result as failure."
+ :type 'boolean)
+
(defcustom eshell-pre-command-hook nil
"A hook run before each interactive command is invoked."
:type 'hook)
@@ -541,9 +545,7 @@ implemented via rewriting, rather than as a function."
,(eshell-invokify-arg body t)))
(setcar for-items (cadr for-items))
(setcdr for-items (cddr for-items)))
- (eshell-close-handles
- eshell-last-command-status
- (list 'quote eshell-last-command-result))))))
+ (eshell-close-handles)))))
(defun eshell-structure-basic-command (func names keyword test body
&optional else)
@@ -551,10 +553,11 @@ implemented via rewriting, rather than as a function."
The first of NAMES should be the positive form, and the second the
negative. It's not likely that users should ever need to call this
function."
- ;; If the test form begins with `eshell-convert', it means
- ;; something data-wise will be returned, and we should let
- ;; that determine the truth of the statement.
- (unless (eq (car test) 'eshell-convert)
+ ;; If the test form begins with `eshell-convert' or
+ ;; `eshell-escape-arg', it means something data-wise will be
+ ;; returned, and we should let that determine the truth of the
+ ;; statement.
+ (unless (memq (car test) '(eshell-convert eshell-escape-arg))
(setq test
`(progn ,test
(eshell-exit-success-p))))
@@ -574,9 +577,7 @@ function."
`(let ((eshell-command-body '(nil))
(eshell-test-body '(nil)))
(,func ,test ,body ,else)
- (eshell-close-handles
- eshell-last-command-status
- (list 'quote eshell-last-command-result))))
+ (eshell-close-handles)))
(defun eshell-rewrite-while-command (terms)
"Rewrite a `while' command into its equivalent Eshell command form.
@@ -1415,43 +1416,53 @@ via `eshell-errorn'."
(defun eshell-lisp-command (object &optional args)
"Insert Lisp OBJECT, using ARGS if a function."
(catch 'eshell-external ; deferred to an external command
+ (setq eshell-last-command-status 0
+ eshell-last-arguments args)
(let* ((eshell-ensure-newline-p (eshell-interactive-output-p))
+ (command-form-p (functionp object))
(result
- (if (functionp object)
- (progn
- (setq eshell-last-arguments args
- eshell-last-command-name
+ (if command-form-p
+ (let ((numeric (not (get object
+ 'eshell-no-numeric-conversions)))
+ (fname-args (get object 'eshell-filename-arguments)))
+ (when (or numeric fname-args)
+ (while args
+ (let ((arg (car args)))
+ (cond
+ ((and numeric (stringp arg) (> (length arg) 0)
+ (text-property-any 0 (length arg)
+ 'number t arg))
+ ;; If any of the arguments are flagged as
+ ;; numbers waiting for conversion, convert
+ ;; them now.
+ (setcar args (string-to-number arg)))
+ ((and fname-args (stringp arg)
+ (string-equal arg "~"))
+ ;; If any of the arguments match "~",
+ ;; prepend "./" to treat it as a regular
+ ;; file name.
+ (setcar args (concat "./" arg)))))
+ (setq args (cdr args))))
+ (setq eshell-last-command-name
(concat "#<function " (symbol-name object) ">"))
- (let ((numeric (not (get object
- 'eshell-no-numeric-conversions)))
- (fname-args (get object 'eshell-filename-arguments)))
- (when (or numeric fname-args)
- (while args
- (let ((arg (car args)))
- (cond ((and numeric (stringp arg) (> (length arg) 0)
- (text-property-any 0 (length arg)
- 'number t arg))
- ;; If any of the arguments are
- ;; flagged as numbers waiting for
- ;; conversion, convert them now.
- (setcar args (string-to-number arg)))
- ((and fname-args (stringp arg)
- (string-equal arg "~"))
- ;; If any of the arguments match "~",
- ;; prepend "./" to treat it as a
- ;; regular file name.
- (setcar args (concat "./" arg)))))
- (setq args (cdr args)))))
(eshell-apply object eshell-last-arguments))
- (setq eshell-last-arguments args
- eshell-last-command-name "#<Lisp object>")
+ (setq eshell-last-command-name "#<Lisp object>")
(eshell-eval object))))
(if (and eshell-ensure-newline-p
(save-excursion
(goto-char eshell-last-output-end)
(not (bolp))))
(eshell-print "\n"))
- (eshell-close-handles 0 (list 'quote result)))))
+ (eshell-close-handles
+ ;; If `eshell-lisp-form-nil-is-failure' is non-nil, Lisp forms
+ ;; that succeeded but have a nil result should have an exit
+ ;; status of 2.
+ (when (and eshell-lisp-form-nil-is-failure
+ (not command-form-p)
+ (= eshell-last-command-status 0)
+ (not result))
+ 2)
+ (list 'quote result)))))
(defalias 'eshell-lisp-command* #'eshell-lisp-command)
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index 68e52a2c9c8..27703976f6d 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -254,6 +254,30 @@ a nil value of mode defaults to `insert'."
(setq idx (1+ idx))))
handles)
+(defun eshell-close-handles (&optional exit-code result handles)
+ "Close all of the current HANDLES, taking refcounts into account.
+If HANDLES is nil, use `eshell-current-handles'.
+
+EXIT-CODE is the process exit code (zero, if the command
+completed successfully). If nil, then use the exit code already
+set in `eshell-last-command-status'.
+
+RESULT is the quoted value of the last command. If nil, then use
+the value already set in `eshell-last-command-result'."
+ (when exit-code
+ (setq eshell-last-command-status exit-code))
+ (when result
+ (cl-assert (eq (car result) 'quote))
+ (setq eshell-last-command-result (cadr result)))
+ (let ((handles (or handles eshell-current-handles)))
+ (dotimes (idx eshell-number-of-handles)
+ (when-let ((handle (aref handles idx)))
+ (setcdr handle (1- (cdr handle)))
+ (when (= (cdr handle) 0)
+ (dolist (target (ensure-list (car (aref handles idx))))
+ (eshell-close-target target (= eshell-last-command-status 0)))
+ (setcar handle nil))))))
+
(defun eshell-close-target (target status)
"Close an output TARGET, passing STATUS as the result.
STATUS should be non-nil on successful termination of the output."
@@ -305,32 +329,6 @@ STATUS should be non-nil on successful termination of the output."
((consp target)
(apply (car target) status (cdr target)))))
-(defun eshell-close-handles (exit-code &optional result handles)
- "Close all of the current handles, taking refcounts into account.
-EXIT-CODE is the process exit code; mainly, it is zero, if the command
-completed successfully. RESULT is the quoted value of the last
-command. If nil, then the meta variables for keeping track of the
-last execution result should not be changed."
- (let ((idx 0))
- (cl-assert (or (not result) (eq (car result) 'quote)))
- (setq eshell-last-command-status exit-code
- eshell-last-command-result (cadr result))
- (while (< idx eshell-number-of-handles)
- (let ((handles (or handles eshell-current-handles)))
- (when (aref handles idx)
- (setcdr (aref handles idx)
- (1- (cdr (aref handles idx))))
- (when (= (cdr (aref handles idx)) 0)
- (let ((target (car (aref handles idx))))
- (if (not (listp target))
- (eshell-close-target target (= exit-code 0))
- (while target
- (eshell-close-target (car target) (= exit-code 0))
- (setq target (cdr target)))))
- (setcar (aref handles idx) nil))))
- (setq idx (1+ idx)))
- nil))
-
(defun eshell-kill-append (string)
"Call `kill-append' with STRING, if it is indeed a string."
(if (stringp string)
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index 99b43661f2c..c367b5cd643 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -346,7 +346,9 @@ Used only on systems which do not support async subprocesses.")
(defvar eshell-last-output-end) ;Defined in esh-mode.el.
(eshell-update-markers eshell-last-output-end)
;; Simulate the effect of eshell-sentinel.
- (eshell-close-handles (if (numberp exit-status) exit-status -1))
+ (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)
(or (bound-and-true-p eshell-in-pipeline-p)
(setq eshell-last-sync-output-start nil))
@@ -398,40 +400,36 @@ PROC is the process that's exiting. STRING is the exit message."
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
(unwind-protect
- (let ((entry (assq proc eshell-process-list)))
-; (if (not entry)
-; (error "Sentinel called for unowned process `%s'"
-; (process-name proc))
- (when entry
- (unwind-protect
- (progn
- (unless (string= string "run")
- ;; Write the exit message if the status is
- ;; abnormal and the process is already writing
- ;; to the terminal.
- (when (and (eq proc (eshell-tail-process))
- (not (string-match "^\\(finished\\|exited\\)"
- string)))
- (funcall (process-filter proc) proc string))
- (let ((handles (nth 1 entry))
- (str (prog1 (nth 3 entry)
- (setf (nth 3 entry) nil)))
- (status (process-exit-status proc)))
- ;; If we're in the middle of handling output
- ;; from this process then schedule the EOF for
- ;; later.
- (letrec ((finish-io
- (lambda ()
- (if (nth 4 entry)
- (run-at-time 0 nil finish-io)
- (when str
- (ignore-error 'eshell-pipe-broken
- (eshell-output-object
- str nil handles)))
- (eshell-close-handles
- status 'nil handles)))))
- (funcall finish-io)))))
- (eshell-remove-process-entry entry))))
+ (when-let ((entry (assq proc eshell-process-list)))
+ (unwind-protect
+ (unless (string= string "run")
+ ;; Write the exit message if the status is
+ ;; abnormal and the process is already writing
+ ;; to the terminal.
+ (when (and (eq proc (eshell-tail-process))
+ (not (string-match "^\\(finished\\|exited\\)"
+ string)))
+ (funcall (process-filter proc) proc string))
+ (let ((handles (nth 1 entry))
+ (str (prog1 (nth 3 entry)
+ (setf (nth 3 entry) nil)))
+ (status (process-exit-status proc)))
+ ;; If we're in the middle of handling output
+ ;; from this process then schedule the EOF for
+ ;; later.
+ (letrec ((finish-io
+ (lambda ()
+ (if (nth 4 entry)
+ (run-at-time 0 nil finish-io)
+ (when str
+ (ignore-error 'eshell-pipe-broken
+ (eshell-output-object
+ str nil handles)))
+ (eshell-close-handles
+ status (list 'quote (= status 0))
+ handles)))))
+ (funcall finish-io))))
+ (eshell-remove-process-entry entry)))
(eshell-kill-process-function proc string)))))
(defun eshell-process-interact (func &optional all query)
diff --git a/lisp/faces.el b/lisp/faces.el
index c7acbf57587..390ddbf606a 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -2046,18 +2046,29 @@ as backgrounds."
(when msg (message "Color: `%s'" color))
color))
-(defun face-at-point (&optional thing multiple)
- "Return the face of the character after point.
-If it has more than one face, return the first one.
-If THING is non-nil try first to get a face name from the buffer.
-IF MULTIPLE is non-nil, return a list of all faces.
-Return nil if there is no face."
+(defun face-at-point (&optional text multiple)
+ "Return a face name from point in the current buffer.
+This function is meant to be used as a conveniency function for
+providing defaults when prompting the user for a face name.
+
+If TEXT is non-nil, return the text at point if it names an
+existing face.
+
+Otherwise, look at the faces in effect at point as text
+properties or overlay properties, and return one of these face
+names.
+
+IF MULTIPLE is non-nil, return a list of faces.
+
+Return nil if there is no face at point.
+
+This function is not meant for handling faces programatically; to
+do that, use `get-text-property' and `get-char-property'."
(let (faces)
- (if thing
- ;; Try to get a face name from the buffer.
- (let ((face (intern-soft (thing-at-point 'symbol))))
- (if (facep face)
- (push face faces))))
+ (when text
+ ;; Try to get a face name from the buffer.
+ (when-let ((face (thing-at-point 'face)))
+ (push face faces)))
;; Add the named faces that the `read-face-name' or `face' property uses.
(let ((faceprop (or (get-char-property (point) 'read-face-name)
(get-char-property (point) 'face))))
diff --git a/lisp/finder.el b/lisp/finder.el
index 73072c0cd48..08d20963b46 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -77,6 +77,7 @@ Each element has the form (KEYWORD . DESCRIPTION).")
(defvar-keymap finder-mode-map
:doc "Keymap used in `finder-mode'."
+ :parent special-mode-map
"SPC" #'finder-select
"f" #'finder-select
"<follow-link>" 'mouse-face
@@ -420,15 +421,14 @@ FILE should be in a form suitable for passing to `locate-library'."
(interactive)
(finder-list-keywords))
-(define-derived-mode finder-mode nil "Finder"
+(define-derived-mode finder-mode special-mode "Finder"
"Major mode for browsing package documentation.
\\<finder-mode-map>
\\[finder-select] more help for the item on the current line
-\\[finder-exit] exit Finder mode and kill the Finder buffer."
- :syntax-table finder-mode-syntax-table
+\\[finder-exit] exit Finder mode and kill the Finder buffer.
+
+\\{finder-mode-map}"
:interactive nil
- (setq buffer-read-only t
- buffer-undo-list t)
(setq-local finder-headmark nil))
(defun finder-summary ()
@@ -436,9 +436,9 @@ FILE should be in a form suitable for passing to `locate-library'."
(interactive nil finder-mode)
(message "%s"
(substitute-command-keys
- "\\<finder-mode-map>\\[finder-select] = select, \
-\\[finder-mouse-select] = select, \\[finder-list-keywords] = to \
-finder directory, \\[finder-exit] = quit, \\[finder-summary] = help")))
+ "\\<finder-mode-map>\\[finder-select] select, \
+\\[finder-mouse-select] select, \\[finder-list-keywords] go to \
+finder directory, \\[finder-exit] quit, \\[finder-summary] help")))
(defun finder-exit ()
"Exit Finder mode.
diff --git a/lisp/gnus/deuglify.el b/lisp/gnus/deuglify.el
index 732c6062b8b..41fc2d83ac3 100644
--- a/lisp/gnus/deuglify.el
+++ b/lisp/gnus/deuglify.el
@@ -223,6 +223,7 @@
(defconst gnus-outlook-deuglify-version "1.5 Gnus version"
"Version of gnus-outlook-deuglify.")
+(make-obsolete-variable 'gnus-outlook-deuglify-version 'emacs-version "29.1")
;;; User Customizable Variables:
diff --git a/lisp/gnus/gnus-diary.el b/lisp/gnus/gnus-diary.el
index cd2b53064b9..6028d4fcb2f 100644
--- a/lisp/gnus/gnus-diary.el
+++ b/lisp/gnus/gnus-diary.el
@@ -65,8 +65,9 @@ There are currently two built-in format functions:
(const :tag "french" gnus-diary-delay-format-french)
(symbol :tag "other")))
-(defconst gnus-diary-version nndiary-version
+(defconst gnus-diary-version "0.2-b14"
"Current Diary back end version.")
+(make-obsolete-variable 'gnus-diary-version 'emacs-version "29.1")
;; Compatibility functions ==================================================
@@ -377,8 +378,9 @@ If ARG (or prefix) is non-nil, force prompting for all fields."
(defun gnus-diary-version ()
"Current Diary back end version."
+ (declare (obsolete emacs-version "29.1"))
(interactive)
- (message "NNDiary version %s" nndiary-version))
+ (message "NNDiary version %s" gnus-diary-version))
(provide 'gnus-diary)
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index d1ad5bd7b2d..4c93814e0dc 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -40,17 +40,14 @@
(defcustom gnus-completing-read-function 'gnus-emacs-completing-read
"Function use to do completing read."
- :version "24.1"
+ :version "29.1"
:group 'gnus-meta
:type '(radio (function-item
:doc "Use Emacs standard `completing-read' function."
gnus-emacs-completing-read)
(function-item
:doc "Use `ido-completing-read' function."
- gnus-ido-completing-read)
- (function-item
- :doc "Use iswitchb based completing-read function."
- gnus-iswitchb-completing-read)))
+ gnus-ido-completing-read)))
(defcustom gnus-completion-styles
(append (when (and (assq 'substring completion-styles-alist)
@@ -1202,6 +1199,7 @@ SPEC is a predicate specifier that contains stuff like `or', `and',
(defun gnus-iswitchb-completing-read (prompt collection &optional require-match
initial-input history def)
"`iswitchb' based completing-read function."
+ (declare (obsolete nil "29.1"))
;; Make sure iswitchb is loaded before we let-bind its variables.
;; If it is loaded inside the let, variables can become unbound afterwards.
(require 'iswitchb)
diff --git a/lisp/gnus/gnus-uu.el b/lisp/gnus/gnus-uu.el
index 6990d8ee778..ee6cab365f3 100644
--- a/lisp/gnus/gnus-uu.el
+++ b/lisp/gnus/gnus-uu.el
@@ -260,9 +260,10 @@ Default is t."
"Non-nil means that files will be viewed with metamail.
The gnus-uu viewing functions will be ignored and gnus-uu will try
to guess at a content-type based on file name suffixes. Default
-it nil."
+is nil."
:group 'gnus-extract
:type 'boolean)
+(make-obsolete-variable 'gnus-uu-view-with-metamail "don't use it." "29.1")
(defcustom gnus-uu-unmark-articles-not-decoded nil
"If non-nil, gnus-uu will mark unsuccessfully decoded articles as unread.
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index b036978efa8..0afd873a5df 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -4166,8 +4166,7 @@ prompt the user for the name of an NNTP server to use."
;; file.
(unless (string-match "^Gnus" gnus-version)
(load "gnus-load" nil t))
- (unless (or (byte-code-function-p (symbol-function 'gnus))
- (subr-native-elisp-p (symbol-function 'gnus)))
+ (unless (compiled-function-p (symbol-function 'gnus))
(message "You should compile Gnus")
(sit-for 2))
(let ((gnus-action-message-log (list nil)))
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 00a27fb5f51..8a3967f3461 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -2086,6 +2086,7 @@ You must have the \"hashcash\" binary installed, see `hashcash-path'."
(defun message-mark-active-p ()
"Non-nil means the mark and region are currently active in this buffer."
+ (declare (obsolete mark-active "29.1"))
mark-active)
(defun message-unquote-tokens (elems)
@@ -2953,12 +2954,12 @@ Consider adding this function to `message-header-setup-hook'"
["Fill Yanked Message" message-fill-yanked-message t]
["Insert Signature" message-insert-signature t]
["Caesar (rot13) Message" message-caesar-buffer-body t]
- ["Caesar (rot13) Region" message-caesar-region (message-mark-active-p)]
+ ["Caesar (rot13) Region" message-caesar-region mark-active]
["Elide Region" message-elide-region
- :active (message-mark-active-p)
+ :active mark-active
:help "Replace text in region with an ellipsis"]
["Delete Outside Region" message-delete-not-region
- :active (message-mark-active-p)
+ :active mark-active
:help "Delete all quoted text outside region"]
["Kill To Signature" message-kill-to-signature t]
["Newline and Reformat" message-newline-and-reformat t]
@@ -2966,7 +2967,7 @@ Consider adding this function to `message-header-setup-hook'"
["Spellcheck" ispell-message :help "Spellcheck this message"]
"----"
["Insert Region Marked" message-mark-inserted-region
- :active (message-mark-active-p) :help "Mark region with enclosing tags"]
+ :active mark-active :help "Mark region with enclosing tags"]
["Insert File Marked..." message-mark-insert-file
:help "Insert file at point marked with enclosing tags"]
["Attach File..." mml-attach-file t]
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index 79217d34001..1417ecdccc8 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -117,8 +117,7 @@
(cond ((fboundp 'libxml-parse-html-region) 'shr)
((executable-find "w3m") 'gnus-w3m)
((executable-find "links") 'links)
- ((executable-find "lynx") 'lynx)
- ((locate-library "html2text") 'html2text))
+ ((executable-find "lynx") 'lynx))
"Render of HTML contents.
It is one of defined renderer types, or a rendering function.
The defined renderer types are:
@@ -127,16 +126,14 @@ The defined renderer types are:
`w3m': use emacs-w3m;
`w3m-standalone': use plain w3m;
`links': use links;
-`lynx': use lynx;
-`html2text': use html2text."
- :version "27.1"
+`lynx': use lynx."
+ :version "29.1"
:type '(choice (const shr)
(const gnus-w3m)
(const w3m :tag "emacs-w3m")
(const w3m-standalone :tag "standalone w3m" )
(const links)
(const lynx)
- (const html2text)
(function))
:group 'mime-display)
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index 5cd57d2f801..e8291cfe6f7 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -35,7 +35,6 @@
(declare-function gnus-setup-posting-charset "gnus-msg" (group))
(autoload 'gnus-completing-read "gnus-util")
(autoload 'message-fetch-field "message")
-(autoload 'message-mark-active-p "message")
(autoload 'message-info "message")
(autoload 'fill-flowed-encode "flow-fill")
(autoload 'message-posting-charset "message")
@@ -1236,7 +1235,7 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
;;
;;["Narrow" mml-narrow-to-part t]
["Quote MML in region" mml-quote-region
- :active (message-mark-active-p)
+ :active mark-active
:help "Quote MML tags in region"]
["Validate MML" mml-validate t]
["Preview" mml-preview t]
diff --git a/lisp/gnus/nnagent.el b/lisp/gnus/nnagent.el
index 60140a46411..d7e32e45809 100644
--- a/lisp/gnus/nnagent.el
+++ b/lisp/gnus/nnagent.el
@@ -35,6 +35,7 @@
(defconst nnagent-version "nnagent 1.0")
+(make-obsolete-variable 'nnagent-version 'emacs-version "29.1")
(defvoo nnagent-directory nil
"Internal variable."
diff --git a/lisp/gnus/nnbabyl.el b/lisp/gnus/nnbabyl.el
index ff0dea8ecdd..5f9903a5b06 100644
--- a/lisp/gnus/nnbabyl.el
+++ b/lisp/gnus/nnbabyl.el
@@ -55,6 +55,7 @@
(defconst nnbabyl-version "nnbabyl 1.0"
"nnbabyl version.")
+(make-obsolete-variable 'nnbabyl-version 'emacs-version "29.1")
(defvoo nnbabyl-mbox-buffer nil)
(defvoo nnbabyl-current-group nil)
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index bd60c43f59d..14540ac7e87 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -234,9 +234,11 @@ all. This may very well take some time.")
(defconst nndiary-version "0.2-b14"
"Current Diary back end version.")
+(make-obsolete-variable 'nndiary-version 'emacs-version "29.1")
(defun nndiary-version ()
"Current Diary back end version."
+ (declare (obsolete emacs-version "29.1"))
(interactive)
(message "NNDiary version %s" nndiary-version))
diff --git a/lisp/gnus/nndir.el b/lisp/gnus/nndir.el
index 2ca25534ce1..75a6ace107a 100644
--- a/lisp/gnus/nndir.el
+++ b/lisp/gnus/nndir.el
@@ -48,6 +48,7 @@
(defvoo nndir-status-string "" nil nnmh-status-string)
(defconst nndir-version "nndir 1.0")
+(make-obsolete-variable 'nndir-version 'emacs-version "29.1")
diff --git a/lisp/gnus/nndoc.el b/lisp/gnus/nndoc.el
index 19ccce47b50..cdff7c9accf 100644
--- a/lisp/gnus/nndoc.el
+++ b/lisp/gnus/nndoc.el
@@ -218,6 +218,7 @@ from the document.")
(defconst nndoc-version "nndoc 1.0"
"nndoc version.")
+(make-obsolete-variable 'nndoc-version 'emacs-version "29.1")
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index fa88b8a87e0..f21e4faf559 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -56,6 +56,7 @@ are generated if and only if they are also in `message-draft-headers'."
(defvoo nndraft-current-directory nil nil nnmh-current-directory)
(defconst nndraft-version "nndraft 1.0")
+(make-obsolete-variable 'nndraft-version 'emacs-version "29.1")
(defvoo nndraft-status-string "" nil nnmh-status-string)
diff --git a/lisp/gnus/nneething.el b/lisp/gnus/nneething.el
index 0c565a8230c..ff72842a2ee 100644
--- a/lisp/gnus/nneething.el
+++ b/lisp/gnus/nneething.el
@@ -57,6 +57,7 @@ included.")
(defconst nneething-version "nneething 1.0"
"nneething version.")
+(make-obsolete-variable 'nneething-version 'emacs-version "29.1")
(defvoo nneething-current-directory nil
"Current news group directory.")
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index c3f7073a7b8..a2b461c15f0 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -91,6 +91,7 @@ message, a huge time saver for large mailboxes.")
(defconst nnfolder-version "nnfolder 2.0"
"nnfolder version.")
+(make-obsolete-variable 'nnfolder-version 'emacs-version "29.1")
(defconst nnfolder-article-marker "X-Gnus-Article-Number: "
"String used to demarcate what the article number for a message is.")
diff --git a/lisp/gnus/nnmaildir.el b/lisp/gnus/nnmaildir.el
index 3dc74c95fb3..4d1ecbf8642 100644
--- a/lisp/gnus/nnmaildir.el
+++ b/lisp/gnus/nnmaildir.el
@@ -62,6 +62,7 @@
(require 'subr-x))
(defconst nnmaildir-version "Gnus")
+(make-obsolete-variable 'nnmaildir-version 'emacs-version "29.1")
(defconst nnmaildir-flag-mark-mapping
'((?F . tick)
diff --git a/lisp/gnus/nnmbox.el b/lisp/gnus/nnmbox.el
index 96ecc34e156..5735c97805e 100644
--- a/lisp/gnus/nnmbox.el
+++ b/lisp/gnus/nnmbox.el
@@ -52,6 +52,7 @@
(defconst nnmbox-version "nnmbox 1.0"
"nnmbox version.")
+(make-obsolete-variable 'nnmbox-version 'emacs-version "29.1")
(defvoo nnmbox-current-group nil
"Current nnmbox news group directory.")
diff --git a/lisp/gnus/nnmh.el b/lisp/gnus/nnmh.el
index 3902af7d2f6..bced527d03f 100644
--- a/lisp/gnus/nnmh.el
+++ b/lisp/gnus/nnmh.el
@@ -55,6 +55,7 @@ as unread by Gnus.")
(defconst nnmh-version "nnmh 1.0"
"nnmh version.")
+(make-obsolete-variable 'nnmh-version 'emacs-version "29.1")
(defvoo nnmh-current-directory nil
"Current news group directory.")
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index 7fe2b516cce..ae726ba0f7b 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -89,6 +89,7 @@ non-nil.")
(defconst nnml-version "nnml 1.0"
"nnml version.")
+(make-obsolete-variable 'nnml-version 'emacs-version "29.1")
(defvoo nnml-nov-file-name ".overview")
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index 8c96d3e0678..99e7b2a6f3f 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -71,6 +71,7 @@ this variable to the list of fields to be ignored.")
(defvoo nnrss-status-string "")
(defconst nnrss-version "nnrss 1.0")
+(make-obsolete-variable 'nnrss-version 'emacs-version "29.1")
(defvar nnrss-group-alist '()
"List of RSS addresses.")
diff --git a/lisp/gnus/nnspool.el b/lisp/gnus/nnspool.el
index 39b89abb88a..e5eb4b81604 100644
--- a/lisp/gnus/nnspool.el
+++ b/lisp/gnus/nnspool.el
@@ -114,6 +114,7 @@ there.")
(defconst nnspool-version "nnspool 2.0"
"Version numbers of this version of NNSPOOL.")
+(make-obsolete-variable 'nnspool-version 'emacs-version "29.1")
(defvoo nnspool-current-directory nil
"Current news group directory.")
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index 29570fa8c9f..6fa424a1555 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -259,6 +259,7 @@ update their active files often, this can help.")
(defvoo nntp-connection-alist nil)
(defvoo nntp-status-string "")
(defconst nntp-version "nntp 5.0")
+(make-obsolete-variable 'nntp-version 'emacs-version "29.1")
(defvoo nntp-inhibit-erase nil)
(defvoo nntp-inhibit-output nil)
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index ae4265de7fb..7b192aa1d2e 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -57,6 +57,7 @@ component group will show up when you enter the virtual group.")
(defconst nnvirtual-version "nnvirtual 1.1")
+(make-obsolete-variable 'nnvirtual-version 'emacs-version "29.1")
(defvoo nnvirtual-current-group nil)
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 59a509b2215..74e18285e64 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1005,9 +1005,9 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
(help-fns--analyze-function function))
(file-name (find-lisp-object-file-name
function (if aliased 'defun def)))
- (beg (if (and (or (byte-code-function-p def)
+ (beg (if (and (or (functionp def)
(keymapp def)
- (memq (car-safe def) '(macro lambda closure)))
+ (eq (car-safe def) 'macro))
(stringp file-name)
(help-fns--autoloaded-p function))
(concat
@@ -1040,7 +1040,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)."
(t "Lisp function"))))
((or (eq (car-safe def) 'macro)
;; For advised macros, def is a lambda
- ;; expression or a byte-code-function-p, so we
+ ;; expression or a compiled-function-p, so we
;; need to check macros before functions.
(macrop function))
(concat beg "Lisp macro"))
@@ -1534,8 +1534,8 @@ This cancels value editing without updating the value."
(when safe-var
(princ " This variable is safe as a file local variable ")
(princ "if its value\n satisfies the predicate ")
- (princ (if (byte-code-function-p safe-var)
- "which is a byte-compiled expression.\n"
+ (princ (if (compiled-function-p safe-var)
+ "which is a compiled expression.\n"
(format-message "`%s'.\n" safe-var))))))
(add-hook 'help-fns-describe-variable-functions #'help-fns--var-risky)
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index dbcc152c15d..bf7446f151a 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -81,11 +81,9 @@
(eval-when-compile (require 'cl-lib))
(require 'cus-edit)
-(defconst htmlfontify-version 0.21)
-
(defconst hfy-meta-tags
- (format "<meta name=\"generator\" content=\"emacs %s; htmlfontify %0.2f\" />"
- emacs-version htmlfontify-version)
+ (format "<meta name=\"generator\" content=\"emacs %s; htmlfontify\" />"
+ emacs-version)
"The generator meta tag for this version of htmlfontify.")
(defconst htmlfontify-manual "Htmlfontify Manual"
@@ -2392,13 +2390,14 @@ You may also want to set `hfy-page-header' and `hfy-page-footer'."
(let ((file (hfy-initfile)))
(load file 'NOERROR nil nil) ))
-;; Obsolete.
-
(defun hfy-interq (set-a set-b)
"Return the intersection (using `eq') of two lists SET-A and SET-B."
(declare (obsolete seq-intersection "28.1"))
(nreverse (seq-intersection set-a set-b #'eq)))
+(defconst htmlfontify-version 0.21)
+(make-obsolete-variable 'htmlfontify-version 'emacs-version "29.1")
+
(define-obsolete-function-alias 'hfy-prop-invisible-p #'invisible-p "29.1")
(provide 'htmlfontify)
diff --git a/lisp/international/characters.el b/lisp/international/characters.el
index ca28222c815..d6e83c81e74 100644
--- a/lisp/international/characters.el
+++ b/lisp/international/characters.el
@@ -1525,6 +1525,17 @@ Setup `char-width-table' appropriate for non-CJK language environment."
(aset char-acronym-table (+ #xE0021 i) (format " %c TAG" (+ 33 i))))
(aset char-acronym-table #xE007F "->|TAG") ; CANCEL TAG
+(dotimes (i 256)
+ (let* ((vs-number (1+ i))
+ (codepoint (if (< i 16)
+ (+ #xfe00 i)
+ (+ #xe0100 i -16)))
+ (delimiter (cond ((<= vs-number 9) "0")
+ ((<= vs-number 99) "")
+ (t " "))))
+ (aset char-acronym-table codepoint
+ (format "VS%s%s" delimiter vs-number))))
+
;; We can't use the \N{name} things here, because this file is used
;; too early in the build process.
(defvar bidi-control-characters
@@ -1574,7 +1585,9 @@ option `glyphless-char-display'."
#x80 #x9F method))
((eq target 'variation-selectors)
(glyphless-set-char-table-range glyphless-char-display
- #xFE00 #xFE0F method))
+ #xFE00 #xFE0F method)
+ (glyphless-set-char-table-range glyphless-char-display
+ #xE0100 #xE01EF method))
((or (eq target 'format-control)
(eq target 'bidi-control))
(when unicode-category-table
@@ -1647,10 +1660,10 @@ GROUP must be one of these symbols:
that are relevant for bidirectional formatting control,
like U+2069 (PDI) and U+202B (RLE).
`variation-selectors':
- Characters in the range U+FE00..U+FE0F, used for
- selecting alternate glyph presentations, such as
- Emoji vs Text presentation, of the preceding
- character(s).
+ Characters in the range U+FE00..U+FE0F and
+ U+E0100..U+E01EF, used for selecting alternate glyph
+ presentations, such as Emoji vs Text presentation, of
+ the preceding character(s).
`no-font': For GUI frames, characters for which no suitable
font is found; for text-mode frames, characters
that cannot be encoded by `terminal-coding-system'.
diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el
index e652f108dde..431d8369c1e 100644
--- a/lisp/leim/quail/indian.el
+++ b/lisp/leim/quail/indian.el
@@ -702,7 +702,7 @@ is."
;; Probhat Input Method
(quail-define-package
"bengali-probhat" "Bengali" "BngPB" t
- "Probhat keyboard for Bengali/Bangla" nil t nil nil nil nil nil nil nil nil t)
+ "Probhat keyboard for Bengali/Bangla" nil t nil t t nil nil nil nil nil t)
(quail-define-rules
("!" ?!)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 8dad382ac0d..17e82cc0c49 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -154,8 +154,7 @@
;; Load-time macro-expansion can only take effect after setting
;; load-source-file-function because of where it is called in lread.c.
(load "emacs-lisp/macroexp")
-(if (or (byte-code-function-p (symbol-function 'macroexpand-all))
- (subr-native-elisp-p (symbol-function 'macroexpand-all)))
+(if (compiled-function-p (symbol-function 'macroexpand-all))
nil
;; Since loaddefs is not yet loaded, macroexp's uses of pcase will simply
;; fail until pcase is explicitly loaded. This also means that we have to
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index 93af525e39d..a61620b2761 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -388,11 +388,11 @@ gnus-version)
(insert "MH-E " mh-version "\n\n")
;; MH-E compilation details.
(insert "MH-E compilation details:\n")
- (let* ((compiled-mhe (byte-code-function-p (symbol-function 'mh-version)))
+ (let* ((compiled-mhe (compiled-function-p (symbol-function 'mh-version)))
(gnus-compiled-version (if compiled-mhe
(mh-macro-expansion-time-gnus-version)
"N/A")))
- (insert " Byte compiled:\t\t" (if compiled-mhe "yes" "no") "\n"
+ (insert " Compiled:\t\t" (if compiled-mhe "yes" "no") "\n"
" Gnus (compile-time):\t" gnus-compiled-version "\n"
" Gnus (run-time):\t" (mh-run-time-gnus-version) "\n\n"))
;; Emacs version.
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index 637f53e6550..e98767ae7c7 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -361,7 +361,8 @@ AGES is the list of ages that are to be shown."
(mapc (lambda (feed)
(let ((feed-name-symbol (intern (car feed))))
(mapc (lambda (item)
- (when (memq (newsticker--age item) ages)
+ (when (or (memq 'all ages)
+ (memq (newsticker--age item) ages))
(newsticker--treeview-list-add-item
item feed-name-symbol t)))
(newsticker--treeview-list-sort-items
@@ -1218,11 +1219,11 @@ Note: does not update the layout."
(newsticker--treeview-list-update t)
(newsticker--treeview-item-update)
(newsticker--treeview-tree-update-tags)
- (cond (newsticker--treeview-current-feed
- (newsticker--treeview-list-items newsticker--treeview-current-feed))
- (newsticker--treeview-current-vfeed
+ (cond (newsticker--treeview-current-vfeed
(newsticker--treeview-list-items-with-age
- (intern newsticker--treeview-current-vfeed))))
+ (intern newsticker--treeview-current-vfeed)))
+ (newsticker--treeview-current-feed
+ (newsticker--treeview-list-items newsticker--treeview-current-feed)))
(newsticker--treeview-tree-update-highlight)
(newsticker--treeview-list-update-highlight)
(let ((cur-feed (or newsticker--treeview-current-feed
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index d033667e87f..170583f608c 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -324,7 +324,7 @@ arguments to pass to the OPERATION."
(tramp-compat-file-name-concat localname "."))
(tramp-shell-quote-argument
(tramp-compat-file-name-concat localname ".."))))
- (replace-regexp-in-region
+ (tramp-compat-replace-regexp-in-region
(regexp-quote
(tramp-compat-file-name-unquote
(file-name-as-directory localname)))
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index fda1441615e..548999ca1d2 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -325,7 +325,7 @@ arguments to pass to the OPERATION."
;; Starting with Emacs 29, `tramp-archive-file-name-handler' is
;; autoloaded. But it must still be in tramp-loaddefs.el for older
;; Emacsen.
-;;;###autoload(autoload 'tramp-archive-file-name-handler "tramp-archine")
+;;;###autoload(autoload 'tramp-archive-file-name-handler "tramp-archive")
;;;###tramp-autoload
(defun tramp-archive-file-name-handler (operation &rest args)
"Invoke the file archive related OPERATION.
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index b83f9f0724e..203d3ede98f 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -330,6 +330,29 @@ CONDITION can also be a list of error conditions."
(autoload 'netrc-parse "netrc")
(netrc-parse file))))
+;; Function `replace-regexp-in-region' is new in Emacs 28.1.
+(defalias 'tramp-compat-replace-regexp-in-region
+ (if (fboundp 'replace-regexp-in-region)
+ #'replace-regexp-in-region
+ (lambda (regexp replacement &optional start end)
+ (if start
+ (when (< start (point-min))
+ (error "Start before start of buffer"))
+ (setq start (point)))
+ (if end
+ (when (> end (point-max))
+ (error "End after end of buffer"))
+ (setq end (point-max)))
+ (save-excursion
+ (let ((matches 0)
+ (case-fold-search nil))
+ (goto-char start)
+ (while (re-search-forward regexp end t)
+ (replace-match replacement t)
+ (setq matches (1+ matches)))
+ (and (not (zerop matches))
+ matches))))))
+
(dolist (elt (all-completions "tramp-compat-" obarray 'functionp))
(put (intern elt) 'tramp-suppress-trace t))
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 7f385292626..27b359d439b 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -426,7 +426,7 @@ Otherwise, return NAME."
(if (directory-name-p name) #'file-name-as-directory #'identity)
(concat
dir
- (unless (string-equal localname "/")
+ (unless (string-match-p (rx (seq bos (opt "/") eos)) localname)
(with-tramp-file-property
crypt-vec localname (concat (symbol-name op) "-file-name")
(unless (tramp-crypt-send-command
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 0b40ff867f2..ca5e959bea5 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1055,9 +1055,10 @@ file names."
;; code in case of direct copy/move. Apply
;; sanity checks.
(or (not equal-remote)
- (tramp-gvfs-info newname)
- (eq op 'copy)
- (not (tramp-gvfs-info filename))))
+ (and
+ (tramp-gvfs-info newname)
+ (or (eq op 'copy)
+ (not (tramp-gvfs-info filename))))))
(if (or (not equal-remote)
(and equal-remote
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index a2b675cf885..f2e3c48235a 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -4205,14 +4205,17 @@ file exists and nonzero exit status otherwise."
;; by some sh implementations (eg, bash when called as sh) on
;; startup; this way, we avoid the startup file clobbering $PS1.
;; $PROMPT_COMMAND is another way to set the prompt in /bin/bash,
- ;; it must be discarded as well. $HISTFILE is set according to
- ;; `tramp-histfile-override'. $TERM and $INSIDE_EMACS set here to
- ;; ensure they have the correct values when the shell starts, not
- ;; just processes run within the shell. (Which processes include
- ;; our initial probes to ensure the remote shell is usable.)
- ;; For the time being, we assume that all shells interpret -i as
- ;; interactive shell. Must be the last argument, because (for
- ;; example) bash expects long options first.
+ ;; it must be discarded as well. Some ssh daemons (for example,
+ ;; on Android devices) do not acknowledge the $PS1 setting in
+ ;; that call, so we make a further sanity check. (Bug#57044)
+ ;; $HISTFILE is set according to `tramp-histfile-override'. $TERM
+ ;; and $INSIDE_EMACS set here to ensure they have the correct
+ ;; values when the shell starts, not just processes run within the
+ ;; shell. (Which processes include our initial probes to ensure
+ ;; the remote shell is usable.) For the time being, we assume
+ ;; that all shells interpret -i as interactive shell. Must be the
+ ;; last argument, because (for example) bash expects long options
+ ;; first.
(tramp-send-command
vec (format
(concat
@@ -4228,7 +4231,21 @@ file exists and nonzero exit status otherwise."
""))
(tramp-shell-quote-argument tramp-end-of-output)
shell (or (tramp-get-sh-extra-args shell) ""))
- t)
+ t t)
+
+ ;; Sanity check.
+ (tramp-barf-if-no-shell-prompt
+ (tramp-get-connection-process vec) 10
+ "Couldn't find remote shell prompt for %s" shell)
+ (unless
+ (tramp-check-for-regexp
+ (tramp-get-connection-process vec) (regexp-quote tramp-end-of-output))
+ (tramp-message vec 5 "Setting shell prompt")
+ (tramp-send-command
+ vec (format "PS1=%s PS2='' PS3='' PROMPT_COMMAND=''"
+ (tramp-shell-quote-argument tramp-end-of-output))
+ t))
+
;; Check proper HISTFILE setting. We give up when not working.
(when (and (stringp tramp-histfile-override)
(file-name-directory tramp-histfile-override))
@@ -5524,10 +5541,14 @@ Nonexistent directories are removed from spec."
;; "--color=never" argument (for example on FreeBSD).
(when (tramp-send-command-and-check
vec (format "%s -lnd /" result))
- (when (tramp-send-command-and-check
- vec (format
- "%s --color=never -al %s"
- result (tramp-get-remote-null-device vec)))
+ (when (and (tramp-send-command-and-check
+ vec (format
+ "%s --color=never -al %s"
+ result (tramp-get-remote-null-device vec)))
+ (not (string-match-p
+ (regexp-quote "\e")
+ (tramp-get-buffer-string
+ (tramp-get-buffer vec)))))
(setq result (concat result " --color=never")))
(throw 'ls-found result))
(setq dl (cdr dl))))))
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 68f522b060a..df708a2159d 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -3807,10 +3807,6 @@ This is needed for font-lock setup.")
(declare-function dired-get-filename
"dired"
(&optional localp no-error-if-not-filep))
-(declare-function iswitchb-read-buffer
- "iswitchb"
- (prompt &optional
- default require-match _predicate start matches-set))
(declare-function org-agenda-change-all-lines
"org-agenda"
(newhead hdmarker &optional fixface just-this))
@@ -3844,7 +3840,6 @@ This is needed for font-lock setup.")
(defvar calc-embedded-open-formula)
(defvar calc-embedded-open-mode)
(defvar font-lock-unfontify-region-function)
-(defvar iswitchb-temp-buflist)
(defvar org-agenda-tags-todo-honor-ignore-options)
(defvar remember-data-file)
(defvar texmathp-why)
diff --git a/lisp/outline.el b/lisp/outline.el
index 35524a79a90..3250b62f1e7 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -281,7 +281,7 @@ This option is only in effect when `outline-minor-mode-cycle' is non-nil."
[outline-1 outline-2 outline-3 outline-4
outline-5 outline-6 outline-7 outline-8])
-(defcustom outline-minor-mode-use-buttons '(derived-mode . special-mode)
+(defcustom outline-minor-mode-use-buttons '(derived-mode . help-mode)
"Whether to display clickable buttons on the headings.
The value should be a `buffer-match-p' condition.
@@ -294,16 +294,16 @@ buffers (yet) -- that will be amended in a future version."
:version "29.1")
(define-icon outline-open button
- '((emoji "▶️")
- (symbol " ⯈ ")
+ '((emoji "🔽")
+ (symbol " ▼ ")
(text " open "))
"Icon used for buttons for opening a section in outline buffers."
:version "29.1"
:help-echo "Open this section")
(define-icon outline-close button
- '((emoji "🔽")
- (symbol " ⯆ ")
+ '((emoji "▶️")
+ (symbol " ▶ ")
(text " close "))
"Icon used for buttons for closing a section in outline buffers."
:version "29.1"
diff --git a/lisp/play/5x5.el b/lisp/play/5x5.el
index 8fe72ddf593..fb944f4d76a 100644
--- a/lisp/play/5x5.el
+++ b/lisp/play/5x5.el
@@ -82,13 +82,6 @@
;; Non-customize variables.
-(defmacro 5x5-defvar-local (var value doc)
- "Define VAR to VALUE with documentation DOC and make it buffer local."
- (declare (obsolete defvar-local "28.1"))
- `(progn
- (defvar ,var ,value ,doc)
- (make-variable-buffer-local (quote ,var))))
-
(defvar-local 5x5-grid nil
"5x5 grid contents.")
@@ -930,14 +923,15 @@ lest."
;; Support functions
-(define-obsolete-function-alias '5x5-xor 'xor "27.1")
-
(defun 5x5-y-or-n-p (prompt)
"5x5 wrapper for `y-or-n-p' which respects the `5x5-hassle-me' setting."
(if 5x5-hassle-me
(y-or-n-p prompt)
t))
+(define-obsolete-function-alias '5x5-xor #'xor "27.1")
+(define-obsolete-function-alias '5x5-defvar-local #'defvar-local "28.1")
+
(provide '5x5)
;;; 5x5.el ends here
diff --git a/lisp/printing.el b/lisp/printing.el
index 83c9ffc9cbd..534b45c772b 100644
--- a/lisp/printing.el
+++ b/lisp/printing.el
@@ -4,16 +4,9 @@
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Keywords: wp, print, PostScript
-;; Version: 6.9.3
+;; Old-Version: 6.9.3
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
-(defconst pr-version "6.9.3"
- "printing.el, v 6.9.3 <2007/12/09 vinicius>
-
-Please send all bug fixes and enhancements to
- bug-gnu-emacs@gnu.org and Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-")
-
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -63,10 +56,6 @@ Please send all bug fixes and enhancements to
;; spool and to despool PostScript buffer. So, `printing' provides an
;; interface to ps-print package and it also provides some extra stuff.
;;
-;; To download the latest ps-print package see
-;; `https://www.emacswiki.org/cgi-bin/wiki/PsPrintPackage'.
-;; Please, see README file for ps-print installation instructions.
-;;
;; `printing' was inspired by:
;;
;; print-nt.el Frederic Corne <frederic.corne@erli.fr>
@@ -942,11 +931,6 @@ Please send all bug fixes and enhancements to
;;
;; Below are some URL where you can find good utilities.
;;
-;; * For `printing' package:
-;;
-;; printing `https://www.emacswiki.org/cgi-bin/emacs/download/printing.el'
-;; ps-print `https://www.emacswiki.org/cgi-bin/wiki/PsPrintPackage'
-;;
;; * For GNU or Unix system:
;;
;; gs, gv `https://www.gnu.org/software/ghostscript/ghostscript.html'
@@ -1015,10 +999,6 @@ Please send all bug fixes and enhancements to
(require 'lpr)
(require 'ps-print)
-(and (string< ps-print-version "6.6.4")
- (error "`printing' requires `ps-print' package version 6.6.4 or later"))
-
-
(defconst pr-cygwin-system
(and lpr-windows-system (getenv "OSTYPE")
(string-match "cygwin" (getenv "OSTYPE"))))
@@ -3007,9 +2987,7 @@ Calls `pr-update-menus' to adjust menus."
(defconst pr-help-message
- (concat "printing.el version " pr-version
- " ps-print.el version " ps-print-version
- "\n\n
+ "\
Menu Layout
-----------
@@ -3215,14 +3193,12 @@ VI. Customization:
23. Show current settings for `printing', `ps-print' or `lpr'.
24. Quick help for printing menu layout.
-")
+"
"Printing help message.")
(defconst pr-interface-help-message
- (concat "printing.el version " pr-version
- " ps-print.el version " ps-print-version
- "\n\n
+ "\
The printing interface buffer has the same functionality as the printing menu.
The major difference is that the states (like sending PostScript generated to a
file, n-up printing, etc.) are set and saved between printing buffer
@@ -3449,7 +3425,7 @@ The printing interface buffer has the following sections:
Quick help for printing interface buffer and printing menu layout. You can
also quit the printing interface buffer or kill all printing help buffer.
-")
+"
"Printing buffer interface help message.")
@@ -4402,7 +4378,6 @@ Or choose the menu option Printing/Show Settings/printing."
(mapconcat
#'ps-print-quote
(list
- (concat "\n;;; printing.el version " pr-version "\n")
";; internal vars"
(ps-comment-string "emacs-version " emacs-version)
(ps-comment-string "pr-txt-command " pr-txt-command)
@@ -5597,9 +5572,6 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
(switch-to-buffer (get-buffer-create pr-buffer-name))
;; header
- (let ((versions (concat "printing v" pr-version
- " ps-print v" ps-print-version)))
- (widget-insert (make-string (- 79 (length versions)) ?\ ) versions))
(pr-insert-italic "\nCurrent Directory : " 1)
(pr-insert-italic default-directory)
@@ -6213,6 +6185,12 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defconst pr-version "6.9.3"
+ "printing.el, v 6.9.3 <2007/12/09 vinicius>
+
+Please send all bug fixes and enhancements to
+ bug-gnu-emacs@gnu.org and Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>")
+(make-obsolete-variable 'pr-version 'emacs-version "29.1")
(provide 'printing)
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index e19726a7eab..6e42da2d54f 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -4,7 +4,7 @@
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Keywords: wp, ebnf, PostScript
-;; Version: 4.4
+;; Old-Version: 4.4
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
;; This file is part of GNU Emacs.
@@ -22,16 +22,6 @@
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
-(defconst ebnf-version "4.4"
- "ebnf2ps.el, v 4.4 <2007/02/12 vinicius>
-
-Vinicius's last change version. When reporting bugs, please also
-report the version of Emacs, if any, that ebnf2ps was running with.
-
-Please send all bug fixes and enhancements to
- Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>.")
-
-
;;; Commentary:
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -45,20 +35,12 @@ Please send all bug fixes and enhancements to
;;
;; (require 'ebnf2ps)
;;
-;; ebnf2ps uses ps-print package (version 5.2.3 or later), so see ps-print to
+;; ebnf2ps uses ps-print package (bundled with Emacs), so see ps-print to
;; know how to set options like landscape printing, page headings, margins,
;; etc.
;;
-;; NOTE: ps-print zebra stripes and line number options doesn't have effect on
-;; ebnf2ps, they behave as it's turned off.
-;;
-;; For good performance, be sure to byte-compile ebnf2ps.el, e.g.
-;;
-;; M-x byte-compile-file <give the path to ebnf2ps.el when prompted>
-;;
-;; This will generate ebnf2ps.elc, which will be loaded instead of ebnf2ps.el.
-;;
-;; ebnf2ps was tested with GNU Emacs 20.4.1.
+;; NOTE: ps-print zebra stripes and line number options don't have an
+;; effect on ebnf2ps, they behave as if it's turned off.
;;
;;
;; Using ebnf2ps
@@ -1154,9 +1136,6 @@ Please send all bug fixes and enhancements to
(require 'ps-print)
(eval-when-compile (require 'cl-lib))
-(and (string< ps-print-version "5.2.3")
- (error "`ebnf2ps' requires `ps-print' package version 5.2.3 or later"))
-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User Variables:
@@ -2455,8 +2434,6 @@ See also `ebnf-syntax-buffer'."
"Return the current ebnf2ps setup."
(format
"
-;;; ebnf2ps.el version %s
-
;;; Emacs version %S
\(setq ebnf-special-show-delimiter %S
@@ -2525,7 +2502,6 @@ See also `ebnf-syntax-buffer'."
;;; ebnf2ps.el - end of settings
"
- ebnf-version
emacs-version
ebnf-special-show-delimiter
(ps-print-quote ebnf-special-font)
@@ -2958,7 +2934,7 @@ See section \"Actions in Comments\" in ebnf2ps documentation.")
(defvar ebnf-eps-file-alist nil
-"Alist associating file name with EPS header and footer.
+ "Alist associating file name with EPS header and footer.
Each element has the following form:
@@ -5242,11 +5218,7 @@ killed after process termination."
(not (search-forward "& ebnf2ps v"
(line-end-position)
t))
- (progn
- ;; adjust creator comment
- (end-of-line)
- ;; (backward-char)
- (insert " & ebnf2ps v" ebnf-version)
+ (progn
;; insert ebnf settings & engine
(goto-char (point-max))
(search-backward "\n%%EndProlog\n")
@@ -5272,7 +5244,7 @@ killed after process termination."
(format "%d %d" (1+ ebnf-eps-upper-x) (1+ ebnf-eps-upper-y))
"\n%%Title: " filename
"\n%%CreationDate: " (format-time-string "%T %b %d %Y")
- "\n%%Creator: " (user-full-name) " (using ebnf2ps v" ebnf-version ")"
+ "\n%%Creator: " (user-full-name) " (using GNU Emacs " emacs-version ")"
"\n%%DocumentNeededResources: font "
(or ebnf-fonts-required
(setq ebnf-fonts-required
@@ -6350,6 +6322,15 @@ killed after process termination."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defconst ebnf-version "4.4"
+ "ebnf2ps.el, v 4.4 <2007/02/12 vinicius>
+
+Vinicius's last change version. When reporting bugs, please also
+report the version of Emacs, if any, that ebnf2ps was running with.
+
+Please send all bug fixes and enhancements to
+ bug-gnu-emacs@gnu.org and Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>.")
+(make-obsolete-variable 'ebnf-version 'emacs-version "29.1")
(provide 'ebnf2ps)
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index dcd74f0369c..443281c4f07 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -116,12 +116,11 @@
;; non-nil, the line numbers are never touched.
;; 2) Multi-; statements like "do i=1,20 ; j=j+i ; end do" are not handled
;; correctly, but I imagine them to be rare.
-;; 3) Regexps for hilit19 are no longer supported.
-;; 4) For FIXED FORMAT code, use fortran mode.
-;; 5) Preprocessor directives, i.e., lines starting with # are left-justified
+;; 3) For FIXED FORMAT code, use fortran mode.
+;; 4) Preprocessor directives, i.e., lines starting with # are left-justified
;; and are untouched by all case-changing commands. There is, at present, no
;; mechanism for treating multi-line directives (continued by \ ).
-;; 6) f77 do-loops do 10 i=.. ; ; 10 continue are not correctly indented.
+;; 5) f77 do-loops do 10 i=.. ; ; 10 continue are not correctly indented.
;; You are urged to use f90-do loops (with labels if you wish).
;; List of user commands
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 9c2c6405253..c256198b3c1 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -92,6 +92,7 @@
(require 'cl-seq)
(require 'bindat)
(eval-when-compile (require 'pcase))
+(require 'subr-x) ; `string-pad'
(declare-function speedbar-change-initial-expansion-list
"speedbar" (new-default))
@@ -2511,9 +2512,8 @@ means to decode using the coding-system set for the GDB process."
;; Record transactions if logging is enabled.
(when gdb-enable-debug
(push (cons 'recv string) gdb-debug-log)
- (if (and gdb-debug-log-max
- (> (length gdb-debug-log) gdb-debug-log-max))
- (setcdr (nthcdr (1- gdb-debug-log-max) gdb-debug-log) nil)))
+ (when gdb-debug-log-max
+ (setq gdb-debug-log (ntake gdb-debug-log-max gdb-debug-log))))
;; Recall the left over gud-marker-acc from last time.
(setq gud-marker-acc (concat gud-marker-acc string))
@@ -2943,7 +2943,8 @@ Return position where LINE begins."
start-posn)))
(defun gdb-pad-string (string padding)
- (format (concat "%" (number-to-string padding) "s") string))
+ (declare (obsolete string-pad "29.1"))
+ (string-pad string padding nil t))
;; gdb-table struct is a way to programmatically construct simple
;; tables. It help to reliably align columns of data in GDB buffers
@@ -2985,13 +2986,13 @@ calling `gdb-table-string'."
"Return TABLE as a string with columns separated with SEP."
(let ((column-sizes (gdb-table-column-sizes table)))
(mapconcat
- 'identity
+ #'identity
(cl-mapcar
(lambda (row properties)
- (apply 'propertize
- (mapconcat 'identity
- (cl-mapcar (lambda (s x) (gdb-pad-string s x))
- row column-sizes)
+ (apply #'propertize
+ (mapconcat #'identity
+ (cl-mapcar (lambda (s x) (string-pad s x nil t))
+ row column-sizes)
sep)
properties))
(gdb-table-rows table)
@@ -3688,10 +3689,11 @@ in `gdb-memory-format'."
(dolist (row memory)
(insert (concat (gdb-mi--field row 'addr) ":"))
(dolist (column (gdb-mi--field row 'data))
- (insert (gdb-pad-string column
- (+ 2 (gdb-memory-column-width
- gdb-memory-unit
- gdb-memory-format)))))
+ (insert (string-pad column
+ (+ 2 (gdb-memory-column-width
+ gdb-memory-unit
+ gdb-memory-format))
+ nil t)))
(newline)))
;; Show last page instead of empty buffer when out of bounds
(when gdb-memory-last-address
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index be43effed7d..ccc57205757 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -1577,16 +1577,17 @@ into one that invokes an Emacs-enabled debugging session.
(seen-e nil)
(shift (lambda () (push (pop args) new-args))))
- ;; Pass all switches and -e scripts through.
+ ;; Pass all switches and -E/-e scripts through.
(while (and args
(string-match "^-" (car args))
(not (equal "-" (car args)))
(not (equal "--" (car args))))
- (when (equal "-e" (car args))
+ (when (or (equal "-E" (car args)) (equal "-e" (car args)))
;; -e goes with the next arg, so shift one extra.
- (or (funcall shift)
- ;; -e as the last arg is an error in Perl.
- (error "No code specified for -e"))
+ (funcall shift)
+ (or args
+ ;; -E (or -e) as the last arg is an error in Perl.
+ (error "No code specified for %s" (car new-args)))
(setq seen-e t))
(funcall shift))
@@ -1697,7 +1698,7 @@ The directory containing the perl program becomes the initial
working directory and source-file directory for your debugger."
(interactive
(list (gud-query-cmdline 'perldb
- (concat (or (buffer-file-name) "-e 0") " "))))
+ (concat (or (buffer-file-name) "-E 0") " "))))
(gud-common-init command-line 'gud-perldb-massage-args
'gud-perldb-marker-filter)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index d2c24a75810..efad3b52aa9 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3490,9 +3490,10 @@ This function is intended for use in `after-change-functions'."
;;;###autoload
(define-derived-mode js-json-mode js-mode "JSON"
- ;; JSON files can be big. Speed up syntax-ppss.
- (setq-local syntax-propertize-function nil)
- (setq-local js-enabled-frameworks nil))
+ (setq-local js-enabled-frameworks nil)
+ ;; Speed up `syntax-ppss': JSON files can be big but can't hold
+ ;; regexp matchers nor #! thingies (and `js-enabled-frameworks' is nil).
+ (setq-local syntax-propertize-function #'ignore))
;; Since we made JSX support available and automatically-enabled in
;; the base `js-mode' (for ease of use), now `js-jsx-mode' simply
diff --git a/lisp/progmodes/ps-mode.el b/lisp/progmodes/ps-mode.el
index 7c9aee2b2a8..89482d86ce2 100644
--- a/lisp/progmodes/ps-mode.el
+++ b/lisp/progmodes/ps-mode.el
@@ -34,7 +34,6 @@
;;; Code:
-(defconst ps-mode-version "1.1i, 17 May 2008")
(defconst ps-mode-maintainer-address
"Peter Kleiweg <p.c.j.kleiweg@rug.nl>, bug-gnu-emacs@gnu.org")
@@ -519,7 +518,7 @@ Typing \\<ps-run-mode-map>\\[ps-run-goto-error] when the cursor is at the number
(defun ps-mode-show-version ()
"Show current version of PostScript mode."
(interactive)
- (message " *** PostScript Mode (ps-mode) Version %s *** " ps-mode-version))
+ (message " *** PostScript Mode (ps-mode) in GNU Emacs %s *** " emacs-version))
;; From reporter.el
(defvar reporter-prompt-for-summary-p)
@@ -534,7 +533,7 @@ Typing \\<ps-run-mode-map>\\[ps-run-goto-error] when the cursor is at the number
ps-run-font-lock-keywords-2)))
(reporter-submit-bug-report
ps-mode-maintainer-address
- (format "ps-mode.el %s [%s]" ps-mode-version system-type)
+ (format "ps-mode.el %s [%s]" emacs-version system-type)
'(ps-mode-tab
ps-mode-paper-size
ps-mode-print-function
@@ -1094,6 +1093,9 @@ Use line numbers if `ps-run-error-line-numbers' is not nil."
;;
(add-hook 'kill-emacs-hook #'ps-run-cleanup)
+(defconst ps-mode-version "1.1i, 17 May 2008")
+(make-obsolete-variable 'ps-mode-version 'emacs-version "29.1")
+
(provide 'ps-mode)
;;; ps-mode.el ends here
diff --git a/lisp/ps-print.el b/lisp/ps-print.el
index dad4c8ffbac..d67c34e11ab 100644
--- a/lisp/ps-print.el
+++ b/lisp/ps-print.el
@@ -8,21 +8,9 @@
;; Kenichi Handa <handa@gnu.org> (multi-byte characters)
;; Maintainer: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Keywords: wp, print, PostScript
-;; Version: 7.3.5
+;; Old-Version: 7.3.5
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
-(eval-when-compile (require 'cl-lib))
-
-(defconst ps-print-version "7.3.5"
- "ps-print.el, v 7.3.5 <2009/12/23 vinicius>
-
-Vinicius's last change version -- this file may have been edited as part of
-Emacs without changes to the version number. When reporting bugs, please also
-report the version of Emacs, if any, that ps-print was distributed with.
-
-Please send all bug fixes and enhancements to
- bug-gnu-emacs@gnu.org and Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>.")
-
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -1320,11 +1308,11 @@ Please send all bug fixes and enhancements to
;; Known bugs and limitations of ps-print
;; --------------------------------------
;;
-;; Automatic font-attribute detection doesn't work well, especially with
-;; hilit19 and older versions of get-create-face. Users having problems with
-;; auto-font detection should use the lists `ps-italic-faces', `ps-bold-faces'
-;; and `ps-underlined-faces' and/or turn off automatic detection by setting
-;; `ps-auto-font-detect' to nil.
+;; Automatic font-attribute detection doesn't work well. Users having
+;; problems with auto-font detection should use the lists
+;; `ps-italic-faces', `ps-bold-faces' and `ps-underlined-faces' and/or
+;; turn off automatic detection by setting `ps-auto-font-detect' to
+;; nil.
;;
;; Still too slow; could use some hand-optimization.
;;
@@ -1451,6 +1439,7 @@ Please send all bug fixes and enhancements to
;;; Code:
(require 'lpr)
+(eval-when-compile (require 'cl-lib))
;; autoloads for secondary file
(require 'ps-print-loaddefs)
@@ -3596,7 +3585,6 @@ The table depends on the current ps-print setup."
(mapconcat
#'ps-print-quote
(list
- (concat "\n;;; (Emacs) ps-print version " ps-print-version "\n")
";; internal vars"
(ps-comment-string "emacs-version " emacs-version)
(ps-comment-string "lpr-windows-system" lpr-windows-system)
@@ -5347,7 +5335,7 @@ XSTART YSTART are the relative position for the first page in a sheet.")
ps-adobe-tag
"%%Title: " (buffer-name) ; Take job name from name of
; first buffer printed
- "\n%%Creator: ps-print v" ps-print-version
+ "\n%%Creator: GNU Emacs " emacs-version
"\n%%For: " (user-full-name) ;FIXME: may need encoding!
"\n%%CreationDate: " (format-time-string "%T %b %d %Y") ;FIXME: encoding!
"\n%%Orientation: "
@@ -6548,6 +6536,17 @@ If FACE is not a valid face name, use default face."
(unless noninteractive
(add-hook 'kill-emacs-query-functions #'ps-kill-emacs-check))
+(defconst ps-print-version "7.3.5"
+ "ps-print.el, v 7.3.5 <2009/12/23 vinicius>
+
+Vinicius's last change version -- this file may have been edited as part of
+Emacs without changes to the version number. When reporting bugs, please also
+report the version of Emacs, if any, that ps-print was distributed with.
+
+Please send all bug fixes and enhancements to
+ bug-gnu-emacs@gnu.org and Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>.")
+(make-obsolete-variable 'ps-print-version 'emacs-version "29.1")
+
(define-obsolete-function-alias 'ps-print-ensure-fontified #'font-lock-ensure "29.1")
(provide 'ps-print)
diff --git a/lisp/select.el b/lisp/select.el
index e407c224367..5b9cca80a38 100644
--- a/lisp/select.el
+++ b/lisp/select.el
@@ -673,9 +673,12 @@ two markers or an overlay. Otherwise, it is nil."
(let ((str (cond ((stringp value) value)
((setq value (xselect--selection-bounds value))
(with-current-buffer (nth 2 value)
- (buffer-substring (nth 0 value)
- (nth 1 value)))))))
- (xselect--encode-string type str t)))
+ (when (and (>= (nth 0 value) (point-min))
+ (<= (nth 1 value) (point-max)))
+ (buffer-substring (nth 0 value)
+ (nth 1 value))))))))
+ (when str
+ (xselect--encode-string type str t))))
(defun xselect-convert-to-length (_selection _type value)
(let ((len (cond ((stringp value)
diff --git a/lisp/simple.el b/lisp/simple.el
index a4ea345ca5f..1e6e5e11e00 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -6731,7 +6731,8 @@ If Transient Mark mode is disabled, this function normally does
nothing; but if FORCE is non-nil, it deactivates the mark anyway.
Deactivating the mark sets `mark-active' to nil, updates the
-primary selection according to `select-active-regions', and runs
+primary selection according to `select-active-regions' (unless
+`deactivate-mark' is `dont-save'), and runs
`deactivate-mark-hook'.
If Transient Mark mode was temporarily enabled, reset the value
@@ -6742,6 +6743,7 @@ run `deactivate-mark-hook'."
(when (and (if (eq select-active-regions 'only)
(eq (car-safe transient-mark-mode) 'only)
select-active-regions)
+ (not (eq deactivate-mark 'dont-save))
(region-active-p)
(display-selections-p))
;; The var `saved-region-selection', if non-nil, is the text in
@@ -7690,11 +7692,33 @@ not vscroll."
;; But don't vscroll in a keyboard macro.
(not defining-kbd-macro)
(not executing-kbd-macro)
+ ;; Lines are not truncated...
+ (not
+ (and
+ (or truncate-lines
+ (and (integerp truncate-partial-width-windows)
+ (< (window-total-width)
+ truncate-partial-width-windows))
+ (and truncate-partial-width-windows
+ (not (integerp truncate-partial-width-windows))
+ (not (window-full-width-p))))
+ ;; ...or if lines are truncated, this buffer
+ ;; doesn't have very long lines.
+ (long-line-optimizations-p)))
(line-move-partial arg noerror))
(set-window-vscroll nil 0 t)
(if (and line-move-visual
;; Display-based column are incompatible with goal-column.
(not goal-column)
+ ;; Lines aren't truncated.
+ (not
+ (or truncate-lines
+ (and (integerp truncate-partial-width-windows)
+ (< (window-width)
+ truncate-partial-width-windows))
+ (and truncate-partial-width-windows
+ (not (integerp truncate-partial-width-windows))
+ (not (window-full-width-p)))))
;; When the text in the window is scrolled to the left,
;; display-based motion doesn't make sense (because each
;; logical line occupies exactly one screen line).
@@ -8131,10 +8155,11 @@ For motion by visual lines, see `beginning-of-visual-line'."
(line-move (1- arg) t)))
;; Move to beginning-of-line, ignoring fields and invisible text.
- (skip-chars-backward "^\n")
- (while (and (not (bobp)) (invisible-p (1- (point))))
- (goto-char (previous-char-property-change (point)))
- (skip-chars-backward "^\n"))
+ (let ((inhibit-field-text-motion t))
+ (goto-char (line-beginning-position))
+ (while (and (not (bobp)) (invisible-p (1- (point))))
+ (goto-char (previous-char-property-change (point)))
+ (goto-char (line-beginning-position))))
;; Now find first visible char in the line.
(while (and (< (point) orig) (invisible-p (point)))
diff --git a/lisp/subr.el b/lisp/subr.el
index 4b1fc832da1..42ce9148a90 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -4077,6 +4077,12 @@ Otherwise, return nil."
(or (eq 'macro (car def))
(and (autoloadp def) (memq (nth 4 def) '(macro t)))))))
+(defun compiled-function-p (object)
+ "Return non-nil if OBJECT is a function that has been compiled.
+Does not distinguish between functions implemented in machine code
+or byte-code."
+ (or (subrp object) (byte-code-function-p object)))
+
(defun field-at-pos (pos)
"Return the field at position POS, taking stickiness etc into account."
(let ((raw-field (get-char-property (field-beginning pos) 'field)))
diff --git a/lisp/textmodes/emacs-authors-mode.el b/lisp/textmodes/emacs-authors-mode.el
new file mode 100644
index 00000000000..af78ab605e9
--- /dev/null
+++ b/lisp/textmodes/emacs-authors-mode.el
@@ -0,0 +1,145 @@
+;;; emacs-authors-mode.el --- font-locking for etc/AUTHORS -*- lexical-binding: t -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Author: Stefan Kangas <stefan@marxist.se>
+;; Keywords: internal
+
+;; 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:
+
+;; Major mode to display the etc/AUTHORS file from the Emacs
+;; distribution. Provides some basic font locking and not much else.
+
+;;; Code:
+
+(require 'subr-x) ; `emacs-etc--hide-local-variables'
+
+(defgroup emacs-authors-mode nil
+ "Display the \"etc/AUTHORS\" file from the Emacs distribution."
+ :version "29.1"
+ :group 'internal)
+
+(defface emacs-authors-default
+ '((t :inherit variable-pitch))
+ "Default face used to display the \"etc/AUTHORS\" file.
+See also `emacs-authors-mode'."
+ :version "29.1")
+
+(defface emacs-authors-author
+ '((((class color) (min-colors 88) (background light))
+ :foreground "midnight blue"
+ :weight bold :height 1.05
+ :inherit variable-pitch)
+ (((class color) (min-colors 88) (background dark))
+ :foreground "cyan"
+ :weight bold :height 1.05
+ :inherit variable-pitch)
+ (((supports :weight bold) (supports :height 1.05))
+ :weight bold :height 1.05
+ :inherit variable-pitch)
+ (((supports :weight bold))
+ :weight bold :inherit variable-pitch)
+ (t :inherit variable-pitch))
+ "Face used for the author in the \"etc/AUTHORS\" file.
+See also `emacs-authors-mode'."
+ :version "29.1")
+
+(defface emacs-authors-descriptor
+ '((((class color) (min-colors 88) (background light))
+ :foreground "sienna" :inherit variable-pitch)
+ (((class color) (min-colors 88) (background dark))
+ :foreground "peru" :inherit variable-pitch)
+ (t :inherit variable-pitch))
+ "Face used for the description text in the \"etc/AUTHORS\" file.
+See also `emacs-authors-mode'."
+ :version "29.1")
+
+(defface emacs-authors-other-files
+ '((t :inherit emacs-authors-descriptor))
+ "Face used for the \"other files\" text in the \"etc/AUTHORS\" file.
+See also `emacs-authors-mode'."
+ :version "29.1")
+
+(defconst emacs-authors--author-re
+ (rx bol (group (not (any blank "\n")) (+? (not (any ":" "\n")))) ":")
+ "Regexp matching an author in \"etc/AUTHORS\".")
+
+(defvar emacs-authors-mode-font-lock-keywords
+ `((,emacs-authors--author-re
+ 1 'emacs-authors-author)
+ (,(rx (or "wrote"
+ (seq (? "and ") (or "co-wrote" "changed"))))
+ 0 'emacs-authors-descriptor)
+ (,(rx "and " (+ digit) " other files")
+ 0 'emacs-authors-other-files)
+ (,(rx bol (not space) (+ not-newline) eol)
+ 0 'emacs-authors-default)))
+
+(defun emacs-authors-next-author (&optional arg)
+ "Move point to the next author in \"etc/AUTHORS\".
+With a prefix arg ARG, move point that many authors forward."
+ (interactive "p" emacs-authors-mode)
+ (if (< 0 arg)
+ (progn
+ (when (looking-at emacs-authors--author-re)
+ (forward-line 1))
+ (re-search-forward emacs-authors--author-re nil t arg))
+ (when (looking-at emacs-authors--author-re)
+ (forward-line -1))
+ (re-search-backward emacs-authors--author-re nil t (abs arg)))
+ (goto-char (line-beginning-position)))
+
+(defun emacs-authors-prev-author (&optional arg)
+ "Move point to the previous author in \"etc/AUTHORS\".
+With a prefix arg ARG, move point that many authors backward."
+ (interactive "p" emacs-authors-mode)
+ (emacs-authors-next-author (- arg)))
+
+(defvar emacs-authors-imenu-generic-expression
+ `((nil ,(rx bol (group (+ (not ":"))) ": "
+ (or "wrote" "co-wrote" "changed")
+ " ")
+ 1)))
+
+(define-obsolete-variable-alias 'etc-authors-mode-map 'emacs-authors-mode-map "29.1")
+(defvar-keymap emacs-authors-mode-map
+ :doc "Keymap for `emacs-authors-mode'."
+ "n" #'emacs-authors-next-author
+ "p" #'emacs-authors-prev-author)
+
+;;;###autoload
+(define-derived-mode emacs-authors-mode special-mode "Authors View"
+ "Major mode for viewing \"etc/AUTHORS\" from the Emacs distribution.
+Provides some basic font locking and not much else."
+ (setq-local font-lock-defaults
+ '(emacs-authors-mode-font-lock-keywords nil nil ((?_ . "w"))))
+ (setq font-lock-multiline nil)
+ (setq imenu-generic-expression emacs-authors-imenu-generic-expression)
+ (emacs-etc--hide-local-variables))
+
+(define-obsolete-face-alias 'etc-authors-default 'emacs-authors-default "29.1")
+(define-obsolete-face-alias 'etc-authors-author 'emacs-authors-author "29.1")
+(define-obsolete-face-alias 'etc-authors-descriptor 'emacs-authors-descriptor "29.1")
+(define-obsolete-face-alias 'etc-authors-other-files 'emacs-authors-other-files "29.1")
+(define-obsolete-function-alias 'etc-authors-next-author #'emacs-authors-next-author "29.1")
+(define-obsolete-function-alias 'etc-authors-prev-author #'emacs-authors-prev-author "29.1")
+;;;###autoload
+(define-obsolete-function-alias 'etc-authors-mode #'emacs-authors-mode "29.1")
+
+(provide 'emacs-authors-mode)
+;;; emacs-authors-mode.el ends here
diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el
index e6e1f037284..022e17c9343 100644
--- a/lisp/textmodes/emacs-news-mode.el
+++ b/lisp/textmodes/emacs-news-mode.el
@@ -25,6 +25,7 @@
(eval-when-compile (require 'cl-lib))
(require 'outline)
+(require 'subr-x) ; `emacs-etc--hide-local-variables'
(defgroup emacs-news-mode nil
"Major mode for editing and viewing the Emacs NEWS file."
@@ -59,9 +60,12 @@
"C-x C-q" #'emacs-news-view-mode
"<remap> <open-line>" #'emacs-news-open-line)
-(defvar-keymap emacs-news-view-mode-map
- :parent emacs-news-common-map
- "C-x C-q" #'emacs-news-mode)
+(defvar emacs-news-view-mode-map
+ ;; This is defined this way instead of inheriting because we're
+ ;; deriving the mode from `special-mode' and want the keys from there.
+ (let ((map (copy-keymap emacs-news-common-map)))
+ (keymap-set map "C-x C-q" #'emacs-news-mode)
+ map))
(defvar emacs-news-mode-font-lock-keywords
`(("^---$" 0 'emacs-news-does-not-need-documentation)
@@ -73,7 +77,8 @@
outline-minor-mode-cycle t
outline-level (lambda () (length (match-string 2)))
outline-minor-mode-highlight 'append)
- (outline-minor-mode))
+ (outline-minor-mode)
+ (emacs-etc--hide-local-variables))
;;;###autoload
(define-derived-mode emacs-news-mode text-mode "NEWS"
diff --git a/lisp/textmodes/etc-authors-mode.el b/lisp/textmodes/etc-authors-mode.el
deleted file mode 100644
index 7eabdd4c2b8..00000000000
--- a/lisp/textmodes/etc-authors-mode.el
+++ /dev/null
@@ -1,133 +0,0 @@
-;;; etc-authors-mode.el --- font-locking for etc/AUTHORS -*- lexical-binding: t -*-
-
-;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
-
-;; Author: Stefan Kangas <stefan@marxist.se>
-;; Keywords: internal
-
-;; 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:
-
-;; Major mode to display the etc/AUTHORS file from the Emacs
-;; distribution. Provides some basic font locking and not much else.
-
-;;; Code:
-
-(defgroup etc-authors-mode nil
- "Display the \"etc/AUTHORS\" file from the Emacs distribution."
- :version "28.1"
- :group 'internal)
-
-(defface etc-authors-default '((t :inherit variable-pitch))
- "Default face used to display the \"etc/AUTHORS\" file.
-See also `etc-authors-mode'."
- :version "28.1")
-
-(defface etc-authors-author '((((class color) (min-colors 88) (background light))
- :foreground "midnight blue"
- :weight bold :height 1.05
- :inherit variable-pitch)
- (((class color) (min-colors 88) (background dark))
- :foreground "cyan"
- :weight bold :height 1.05
- :inherit variable-pitch)
- (((supports :weight bold) (supports :height 1.05))
- :weight bold :height 1.05
- :inherit variable-pitch)
- (((supports :weight bold))
- :weight bold :inherit variable-pitch)
- (t :inherit variable-pitch))
- "Face used for the author in the \"etc/AUTHORS\" file.
-See also `etc-authors-mode'."
- :version "28.1")
-
-(defface etc-authors-descriptor '((((class color) (min-colors 88) (background light))
- :foreground "sienna" :inherit variable-pitch)
- (((class color) (min-colors 88) (background dark))
- :foreground "peru" :inherit variable-pitch)
- (t :inherit variable-pitch))
- "Face used for the description text in the \"etc/AUTHORS\" file.
-See also `etc-authors-mode'."
- :version "28.1")
-
-(defface etc-authors-other-files '((t :inherit etc-authors-descriptor))
- "Face used for the \"other files\" text in the \"etc/AUTHORS\" file.
-See also `etc-authors-mode'."
- :version "28.1")
-
-(defconst etc-authors--author-re
- (rx bol (group (not (any blank "\n")) (+? (not (any ":" "\n")))) ":")
- "Regexp matching an author in \"etc/AUTHORS\".")
-
-(defvar etc-authors-mode-font-lock-keywords
- `((,etc-authors--author-re
- 1 'etc-authors-author)
- (,(rx (or "wrote"
- (seq (? "and ") (or "co-wrote" "changed"))))
- 0 'etc-authors-descriptor)
- (,(rx "and " (+ digit) " other files")
- 0 'etc-authors-other-files)
- (,(rx bol (not space) (+ not-newline) eol)
- 0 'etc-authors-default)))
-
-(defun etc-authors-mode--hide-local-variables ()
- "Hide local variables in \"etc/AUTHORS\". Used by `etc-authors-mode'."
- (narrow-to-region (point-min)
- (save-excursion
- (goto-char (point-min))
- ;; Obfuscate to avoid this being interpreted
- ;; as a local variable section itself.
- (if (re-search-forward "^Local\sVariables:$" nil t)
- (progn (forward-line -1) (point))
- (point-max)))))
-
-(defun etc-authors-next-author (&optional arg)
- "Move point to the next author in \"etc/AUTHORS\".
-With a prefix arg ARG, move point that many authors forward."
- (interactive "p" etc-authors-mode)
- (if (< 0 arg)
- (progn
- (when (looking-at etc-authors--author-re)
- (forward-line 1))
- (re-search-forward etc-authors--author-re nil t arg))
- (when (looking-at etc-authors--author-re)
- (forward-line -1))
- (re-search-backward etc-authors--author-re nil t (abs arg)))
- (goto-char (line-beginning-position)))
-
-(defun etc-authors-prev-author (&optional arg)
- "Move point to the previous author in \"etc/AUTHORS\".
-With a prefix arg ARG, move point that many authors backward."
- (interactive "p" etc-authors-mode)
- (etc-authors-next-author (- arg)))
-
-(defvar-keymap etc-authors-mode-map
- :doc "Keymap for `etc-authors-mode'."
- "n" #'etc-authors-next-author
- "p" #'etc-authors-prev-author)
-
-;;;###autoload
-(define-derived-mode etc-authors-mode special-mode "Authors View"
- "Major mode for viewing \"etc/AUTHORS\" from the Emacs distribution.
-Provides some basic font locking and not much else."
- (setq-local font-lock-defaults
- '(etc-authors-mode-font-lock-keywords nil nil ((?_ . "w"))))
- (setq font-lock-multiline nil)
- (etc-authors-mode--hide-local-variables))
-
-(provide 'etc-authors-mode)
-;;; etc-authors-mode.el ends here
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
index a7c86fb24f0..462f87d3c1a 100644
--- a/lisp/thingatpt.el
+++ b/lisp/thingatpt.el
@@ -74,7 +74,7 @@ question.
\"things\" include `symbol', `list', `sexp', `defun', `filename',
`existing-filename', `url', `email', `uuid', `word', `sentence',
-`whitespace', `line', and `page'.")
+`whitespace', `line', `face' and `page'.")
;; Basic movement
@@ -166,7 +166,7 @@ positions of the thing found."
THING should be a symbol specifying a type of syntactic entity.
Possibilities include `symbol', `list', `sexp', `defun',
`filename', `existing-filename', `url', `email', `uuid', `word',
-`sentence', `whitespace', `line', `number', and `page'.
+`sentence', `whitespace', `line', `number', `face' and `page'.
When the optional argument NO-PROPERTIES is non-nil,
strip text properties from the return value.
@@ -361,6 +361,15 @@ E.g.:
(put 'existing-filename 'thing-at-point 'thing-at-point-file-at-point)
+;; Faces
+
+(defun thing-at-point-face-at-point (&optional _lax _bounds)
+ "Return the name of the face at point as a symbol."
+ (when-let ((face (thing-at-point 'symbol)))
+ (and (facep face) (intern face))))
+
+(put 'face 'thing-at-point 'thing-at-point-face-at-point)
+
;; URIs
(defvar thing-at-point-beginning-of-url-regexp nil
diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el
index e02d84f1f56..d710578ffff 100644
--- a/lisp/vc/add-log.el
+++ b/lisp/vc/add-log.el
@@ -568,14 +568,12 @@ Compatibility function for \\[next-error] invocations."
;; Select window displaying source file.
(select-window change-log-find-window)))))
-(defvar change-log-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map [?\C-c ?\C-p] #'add-log-edit-prev-comment)
- (define-key map [?\C-c ?\C-n] #'add-log-edit-next-comment)
- (define-key map [?\C-c ?\C-f] #'change-log-find-file)
- (define-key map [?\C-c ?\C-c] #'change-log-goto-source)
- map)
- "Keymap for Change Log major mode.")
+(defvar-keymap change-log-mode-map
+ :doc "Keymap for Change Log major mode."
+ "C-c C-p" #'add-log-edit-prev-comment
+ "C-c C-n" #'add-log-edit-next-comment
+ "C-c C-f" #'change-log-find-file
+ "C-c C-c" #'change-log-goto-source)
(easy-menu-define change-log-mode-menu change-log-mode-map
"Menu for Change Log major mode."
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index aa426446d73..e4a1996c1bb 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -27,8 +27,8 @@
;; to the corresponding source file.
;; Inspired by Pavel Machek's patch-mode.el (<pavel@@atrey.karlin.mff.cuni.cz>)
-;; Some efforts were spent to have it somewhat compatible with XEmacs's
-;; diff-mode as well as with compilation-minor-mode
+;; Some efforts were spent to have it somewhat compatible with
+;; `compilation-minor-mode'.
;; Bugs:
diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el
index 7e15060f8c4..52e356d8e9b 100644
--- a/lisp/vc/ediff-mult.el
+++ b/lisp/vc/ediff-mult.el
@@ -144,20 +144,18 @@ Useful commands (type ? to hide them and free up screen):
(ediff-defvar-local ediff-meta-buffer-map nil
"The keymap for the meta buffer.")
-(defvar ediff-dir-diffs-buffer-map
- (let ((map (make-sparse-keymap)))
- (suppress-keymap map)
- (define-key map "q" #'ediff-bury-dir-diffs-buffer)
- (define-key map " " #'next-line)
- (define-key map "n" #'next-line)
- (define-key map "\C-?" #'previous-line)
- (define-key map "p" #'previous-line)
- (define-key map "C" #'ediff-dir-diff-copy-file)
- (define-key map [mouse-2] #'ediff-dir-diff-copy-file)
- (define-key map [delete] #'previous-line)
- (define-key map [backspace] #'previous-line)
- map)
- "Keymap for buffer showing differences between directories.")
+(defvar-keymap ediff-dir-diffs-buffer-map
+ :doc "Keymap for buffer showing differences between directories."
+ :suppress t
+ "q" #'ediff-bury-dir-diffs-buffer
+ "SPC" #'next-line
+ "n" #'next-line
+ "DEL" #'previous-line
+ "p" #'previous-line
+ "C" #'ediff-dir-diff-copy-file
+ "<mouse-2>" #'ediff-dir-diff-copy-file
+ "<delete>" #'previous-line
+ "<backspace>" #'previous-line)
;; Variable specifying the action to take when the use invokes ediff in the
;; meta buffer. This is usually ediff-registry-action or ediff-filegroup-action
diff --git a/lisp/vc/ediff.el b/lisp/vc/ediff.el
index 84ad5cef90f..94e3fc6d7fe 100644
--- a/lisp/vc/ediff.el
+++ b/lisp/vc/ediff.el
@@ -89,12 +89,11 @@
;; underlining. However, if the region is already underlined by some other
;; overlays, there is no simple way to temporarily remove that residual
;; underlining. This problem occurs when a buffer is highlighted with
-;; hilit19.el or font-lock.el packages. If this residual highlighting gets
-;; in the way, you can do the following. Both font-lock.el and hilit19.el
-;; provide commands for unhighlighting buffers. You can either place these
-;; commands in `ediff-prepare-buffer-hook' (which will unhighlight every
-;; buffer used by Ediff) or you can execute them interactively, at any time
-;; and on any buffer.
+;; font-lock.el packages. If this residual highlighting gets in the way, you
+;; can do the following. font-lock.el provides commands for unhighlighting
+;; buffers. You can either place these commands in `ediff-prepare-buffer-hook'
+;; (which will unhighlight every buffer used by Ediff) or you can execute
+;; them interactively, at any time and in any buffer.
;;; Acknowledgments:
diff --git a/lisp/vc/emerge.el b/lisp/vc/emerge.el
index 422ed5c0a4d..de09be80e7c 100644
--- a/lisp/vc/emerge.el
+++ b/lisp/vc/emerge.el
@@ -2942,6 +2942,7 @@ If some prefix of KEY has a non-prefix definition, it is redefined."
;; Define a key if it (or a prefix) is not already defined in the map.
(defun emerge-define-key-if-possible (keymap key definition)
+ (declare (obsolete keymap-set "29.1"))
;; look up the present definition of the key
(let ((present (lookup-key keymap key)))
(if (integerp present)
@@ -2959,6 +2960,7 @@ If some prefix of KEY has a non-prefix definition, it is redefined."
If the name won't fit on one line, the minibuffer is expanded to hold it,
and the command waits for a keystroke from the user. If the keystroke is
SPC, it is ignored; if it is anything else, it is processed as a command."
+ (declare (obsolete nil "29.1"))
(interactive)
(let ((name (buffer-file-name)))
(or name
diff --git a/lisp/vc/vc-annotate.el b/lisp/vc/vc-annotate.el
index 1f19c4cfe26..a15cf417de3 100644
--- a/lisp/vc/vc-annotate.el
+++ b/lisp/vc/vc-annotate.el
@@ -162,22 +162,20 @@ List of factors, used to expand/compress the time scale. See `vc-annotate'."
:type '(repeat number)
:group 'vc)
-(defvar vc-annotate-mode-map
- (let ((m (make-sparse-keymap)))
- (define-key m "a" #'vc-annotate-revision-previous-to-line)
- (define-key m "d" #'vc-annotate-show-diff-revision-at-line)
- (define-key m "=" #'vc-annotate-show-diff-revision-at-line)
- (define-key m "D" #'vc-annotate-show-changeset-diff-revision-at-line)
- (define-key m "f" #'vc-annotate-find-revision-at-line)
- (define-key m "j" #'vc-annotate-revision-at-line)
- (define-key m "l" #'vc-annotate-show-log-revision-at-line)
- (define-key m "n" #'vc-annotate-next-revision)
- (define-key m "p" #'vc-annotate-prev-revision)
- (define-key m "w" #'vc-annotate-working-revision)
- (define-key m "v" #'vc-annotate-toggle-annotation-visibility)
- (define-key m "\C-m" #'vc-annotate-goto-line)
- m)
- "Local keymap used for VC-Annotate mode.")
+(defvar-keymap vc-annotate-mode-map
+ :doc "Local keymap used for VC-Annotate mode."
+ "a" #'vc-annotate-revision-previous-to-line
+ "d" #'vc-annotate-show-diff-revision-at-line
+ "=" #'vc-annotate-show-diff-revision-at-line
+ "D" #'vc-annotate-show-changeset-diff-revision-at-line
+ "f" #'vc-annotate-find-revision-at-line
+ "j" #'vc-annotate-revision-at-line
+ "l" #'vc-annotate-show-log-revision-at-line
+ "n" #'vc-annotate-next-revision
+ "p" #'vc-annotate-prev-revision
+ "w" #'vc-annotate-working-revision
+ "v" #'vc-annotate-toggle-annotation-visibility
+ "RET" #'vc-annotate-goto-line)
;;; Annotate functionality
diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el
index 072bd72b441..f6b17d4ce09 100644
--- a/lisp/vc/vc-bzr.el
+++ b/lisp/vc/vc-bzr.el
@@ -1008,19 +1008,17 @@ stream. Standard error output is discarded."
;; frob the results accordingly.
(file-relative-name dir (vc-bzr-root dir)))))
-(defvar vc-bzr-shelve-map
- (let ((map (make-sparse-keymap)))
- ;; Turn off vc-dir marking
- (define-key map [mouse-2] #'ignore)
-
- (define-key map [down-mouse-3] #'vc-bzr-shelve-menu)
- (define-key map "\C-k" #'vc-bzr-shelve-delete-at-point)
- (define-key map "=" #'vc-bzr-shelve-show-at-point)
- (define-key map "\C-m" #'vc-bzr-shelve-show-at-point)
- (define-key map "A" #'vc-bzr-shelve-apply-and-keep-at-point)
- (define-key map "P" #'vc-bzr-shelve-apply-at-point)
- (define-key map "S" #'vc-bzr-shelve-snapshot)
- map))
+(defvar-keymap vc-bzr-shelve-map
+ ;; Turn off vc-dir marking
+ "<mouse-2>" #'ignore
+
+ "<down-mouse-3>" #'vc-bzr-shelve-menu
+ "C-k" #'vc-bzr-shelve-delete-at-point
+ "=" #'vc-bzr-shelve-show-at-point
+ "RET" #'vc-bzr-shelve-show-at-point
+ "A" #'vc-bzr-shelve-apply-and-keep-at-point
+ "P" #'vc-bzr-shelve-apply-at-point
+ "S" #'vc-bzr-shelve-snapshot)
(defvar vc-bzr-shelve-menu-map
(let ((map (make-sparse-keymap "Bzr Shelve")))
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index 9335da10065..068a66b25b8 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -1467,17 +1467,13 @@ These are the commands available for use in the file status buffer:
(propertize "Please add backend specific headers here. It's easy!"
'face 'vc-dir-status-warning)))
-(defvar vc-dir-status-mouse-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] #'vc-dir-toggle-mark)
- map)
- "Local keymap for toggling mark.")
+(defvar-keymap vc-dir-status-mouse-map
+ :doc "Local keymap for toggling mark."
+ "<mouse-2>" #'vc-dir-toggle-mark)
-(defvar vc-dir-filename-mouse-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] #'vc-dir-find-file-other-window)
- map)
- "Local keymap for visiting a file.")
+(defvar-keymap vc-dir-filename-mouse-map
+ :doc "Local keymap for visiting a file."
+ "<mouse-2>" #'vc-dir-find-file-other-window)
(defun vc-default-dir-printer (_backend fileentry)
"Pretty print FILEENTRY."
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 8937454d111..46a486a46c3 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -664,32 +664,26 @@ or an empty string if none."
:files files
:update-function update-function)))
-(defvar vc-git-stash-shared-map
- (let ((map (make-sparse-keymap)))
- (define-key map "S" #'vc-git-stash-snapshot)
- (define-key map "C" #'vc-git-stash)
- map))
-
-(defvar vc-git-stash-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map vc-git-stash-shared-map)
- ;; Turn off vc-dir marking
- (define-key map [mouse-2] #'ignore)
-
- (define-key map [down-mouse-3] #'vc-git-stash-menu)
- (define-key map "\C-k" #'vc-git-stash-delete-at-point)
- (define-key map "=" #'vc-git-stash-show-at-point)
- (define-key map "\C-m" #'vc-git-stash-show-at-point)
- (define-key map "A" #'vc-git-stash-apply-at-point)
- (define-key map "P" #'vc-git-stash-pop-at-point)
- map))
-
-(defvar vc-git-stash-button-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map vc-git-stash-shared-map)
- (define-key map [mouse-2] #'push-button)
- (define-key map "\C-m" #'push-button)
- map))
+(defvar-keymap vc-git-stash-shared-map
+ "S" #'vc-git-stash-snapshot
+ "C" #'vc-git-stash)
+
+(defvar-keymap vc-git-stash-map
+ :parent vc-git-stash-shared-map
+ ;; Turn off vc-dir marking
+ "<mouse-2>" #'ignore
+
+ "<down-mouse-3>" #'vc-git-stash-menu
+ "C-k" #'vc-git-stash-delete-at-point
+ "=" #'vc-git-stash-show-at-point
+ "RET" #'vc-git-stash-show-at-point
+ "A" #'vc-git-stash-apply-at-point
+ "P" #'vc-git-stash-pop-at-point)
+
+(defvar-keymap vc-git-stash-button-map
+ :parent vc-git-stash-shared-map
+ "<mouse-2>" #'push-button
+ "RET" #'push-button)
(defconst vc-git-stash-shared-help
"\\<vc-git-stash-shared-map>\\[vc-git-stash]: Create named stash\n\\[vc-git-stash-snapshot]: Snapshot stash")
@@ -910,12 +904,11 @@ If toggling on, also insert its message into the buffer."
standard-output 1 nil
"log" "--max-count=1" "--pretty=format:%B" "HEAD")))))
-(defvar vc-git-log-edit-mode-map
- (let ((map (make-sparse-keymap "Git-Log-Edit")))
- (define-key map "\C-c\C-s" #'vc-git-log-edit-toggle-signoff)
- (define-key map "\C-c\C-n" #'vc-git-log-edit-toggle-no-verify)
- (define-key map "\C-c\C-e" #'vc-git-log-edit-toggle-amend)
- map))
+(defvar-keymap vc-git-log-edit-mode-map
+ :name "Git-Log-Edit"
+ "C-c C-s" #'vc-git-log-edit-toggle-signoff
+ "C-c C-n" #'vc-git-log-edit-toggle-no-verify
+ "C-c C-e" #'vc-git-log-edit-toggle-amend)
(define-derived-mode vc-git-log-edit-mode log-edit-mode "Log-Edit/git"
"Major mode for editing Git log messages.
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index 5fba2b3908a..61976288e35 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -1177,10 +1177,9 @@ If toggling on, also insert its message into the buffer."
standard-output 1 nil
"log" "--limit=1" "--template" "{desc}")))))
-(defvar vc-hg-log-edit-mode-map
- (let ((map (make-sparse-keymap "Hg-Log-Edit")))
- (define-key map "\C-c\C-e" #'vc-hg-log-edit-toggle-amend)
- map))
+(defvar-keymap vc-hg-log-edit-mode-map
+ :name "Hg-Log-Edit"
+ "C-c C-e" #'vc-hg-log-edit-toggle-amend)
(define-derived-mode vc-hg-log-edit-mode log-edit-mode "Log-Edit/hg"
"Major mode for editing Hg log messages.
@@ -1262,9 +1261,7 @@ REV is the revision to check out into WORKFILE."
;;; Hg specific functionality.
-(defvar vc-hg-extra-menu-map
- (let ((map (make-sparse-keymap)))
- map))
+(defvar-keymap vc-hg-extra-menu-map)
(defun vc-hg-extra-menu () vc-hg-extra-menu-map)
diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el
index 405c9bc2ca4..1f0eeb7e18a 100644
--- a/lisp/vc/vc-hooks.el
+++ b/lisp/vc/vc-hooks.el
@@ -855,38 +855,37 @@ In the latter case, VC mode is deactivated for this buffer."
;; Autoloading works fine, but it prevents shortcuts from appearing
;; in the menu because they don't exist yet when the menu is built.
;; (autoload 'vc-prefix-map "vc" nil nil 'keymap)
-(defvar vc-prefix-map
- (let ((map (make-sparse-keymap)))
- (define-key map "a" #'vc-update-change-log)
- (with-suppressed-warnings ((obsolete vc-switch-backend))
- (define-key map "b" #'vc-switch-backend))
- (define-key map "d" #'vc-dir)
- (define-key map "g" #'vc-annotate)
- (define-key map "G" #'vc-ignore)
- (define-key map "h" #'vc-region-history)
- (define-key map "i" #'vc-register)
- (define-key map "l" #'vc-print-log)
- (define-key map "L" #'vc-print-root-log)
- (define-key map "I" #'vc-log-incoming)
- (define-key map "O" #'vc-log-outgoing)
- (define-key map "ML" #'vc-log-mergebase)
- (define-key map "MD" #'vc-diff-mergebase)
- (define-key map "m" #'vc-merge)
- (define-key map "r" #'vc-retrieve-tag)
- (define-key map "s" #'vc-create-tag)
- (define-key map "u" #'vc-revert)
- (define-key map "v" #'vc-next-action)
- (define-key map "+" #'vc-update)
- ;; I'd prefer some kind of symmetry with vc-update:
- (define-key map "P" #'vc-push)
- (define-key map "=" #'vc-diff)
- (define-key map "D" #'vc-root-diff)
- (define-key map "~" #'vc-revision-other-window)
- (define-key map "x" #'vc-delete-file)
- map))
+(defvar-keymap vc-prefix-map
+ "a" #'vc-update-change-log
+ "d" #'vc-dir
+ "g" #'vc-annotate
+ "G" #'vc-ignore
+ "h" #'vc-region-history
+ "i" #'vc-register
+ "l" #'vc-print-log
+ "L" #'vc-print-root-log
+ "I" #'vc-log-incoming
+ "O" #'vc-log-outgoing
+ "M L" #'vc-log-mergebase
+ "M D" #'vc-diff-mergebase
+ "m" #'vc-merge
+ "r" #'vc-retrieve-tag
+ "s" #'vc-create-tag
+ "u" #'vc-revert
+ "v" #'vc-next-action
+ "+" #'vc-update
+ ;; I'd prefer some kind of symmetry with vc-update:
+ "P" #'vc-push
+ "=" #'vc-diff
+ "D" #'vc-root-diff
+ "~" #'vc-revision-other-window
+ "x" #'vc-delete-file)
(fset 'vc-prefix-map vc-prefix-map)
(define-key ctl-x-map "v" 'vc-prefix-map)
+(with-suppressed-warnings ((obsolete vc-switch-backend))
+ (keymap-set vc-prefix-map "b" #'vc-switch-backend))
+
(defvar vc-menu-map
(let ((map (make-sparse-keymap "Version Control")))
;;(define-key map [show-files]
diff --git a/src/Makefile.in b/src/Makefile.in
index 92a8790efdc..a7024bda461 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -845,7 +845,6 @@ ifeq ($(HAVE_NATIVE_COMP):$(NATIVE_DISABLED),yes:)
## List of *.eln files we need to produce in addition to the preloaded
## ones in $(lisp).
elnlisp := \
- emacs-lisp/autoload.eln \
emacs-lisp/byte-opt.eln \
emacs-lisp/bytecomp.eln \
emacs-lisp/cconv.eln \
diff --git a/src/buffer.c b/src/buffer.c
index e5601af5051..98066a2eb60 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1160,7 +1160,8 @@ is first appended to NAME, to speed up finding a non-existent buffer. */)
genbase = name;
else
{
- char number[sizeof "-999999"];
+ enum { bug_52711 = true }; /* https://bugs.gnu.org/57211 */
+ char number[bug_52711 ? INT_BUFSIZE_BOUND (int) + 1 : sizeof "-999999"];
EMACS_INT r = get_random ();
eassume (0 <= r);
int i = r % 1000000;
@@ -6442,6 +6443,24 @@ If nil, these display shortcuts will always remain disabled.
There is no reason to change that value except for debugging purposes. */);
XSETFASTINT (Vlong_line_threshold, 10000);
+ DEFVAR_INT ("large-hscroll-threshold", large_hscroll_threshold,
+ doc: /* Horizontal scroll of truncated lines above which to use redisplay shortcuts.
+
+The value should be a positive integer.
+
+Shortcuts in the display code intended to speed up redisplay for long
+and truncated lines will automatically be enabled when a line's
+horizontal scroll amount is or about to become larger than the value
+of this variable.
+
+This variable has effect only in buffers which contain one or more
+lines whose length is above `long-line-threshold', which see.
+To disable redisplay shortcuts for long truncated line, set this
+variable to `most-positive-fixnum'.
+
+There is no reason to change that value except for debugging purposes. */);
+ large_hscroll_threshold = 10000;
+
defsubr (&Sbuffer_live_p);
defsubr (&Sbuffer_list);
defsubr (&Sget_buffer);
diff --git a/src/eval.c b/src/eval.c
index d82d05797b2..56b42966623 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -57,6 +57,12 @@ Lisp_Object Vrun_hooks;
/* FIXME: We should probably get rid of this! */
Lisp_Object Vsignaling_function;
+/* The handler structure which will catch errors in Lisp hooks called
+ from redisplay. We do not use it for this; we compare it with the
+ handler which is about to be used in signal_or_quit, and if it
+ matches, cause a backtrace to be generated. */
+static struct handler *redisplay_deep_handler;
+
/* These would ordinarily be static, but they need to be visible to GDB. */
bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
@@ -246,6 +252,7 @@ init_eval (void)
lisp_eval_depth = 0;
/* This is less than the initial value of num_nonmacro_input_events. */
when_entered_debugger = -1;
+ redisplay_deep_handler = NULL;
}
/* Ensure that *M is at least A + B if possible, or is its maximum
@@ -333,7 +340,8 @@ call_debugger (Lisp_Object arg)
/* Interrupting redisplay and resuming it later is not safe under
all circumstances. So, when the debugger returns, abort the
interrupted redisplay by going back to the top-level. */
- if (debug_while_redisplaying)
+ if (debug_while_redisplaying
+ && !EQ (Vdebugger, Qdebug_early))
Ftop_level ();
return unbind_to (count, val);
@@ -1556,12 +1564,16 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
ptrdiff_t nargs,
Lisp_Object *args))
{
+ struct handler *old_deep = redisplay_deep_handler;
struct handler *c = push_handler (handlers, CONDITION_CASE);
+ if (redisplaying_p)
+ redisplay_deep_handler = c;
if (sys_setjmp (c->jmp))
{
Lisp_Object val = handlerlist->val;
clobbered_eassert (handlerlist == c);
handlerlist = handlerlist->next;
+ redisplay_deep_handler = old_deep;
return hfun (val, nargs, args);
}
else
@@ -1569,6 +1581,7 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
Lisp_Object val = bfun (nargs, args);
eassert (handlerlist == c);
handlerlist = c->next;
+ redisplay_deep_handler = old_deep;
return val;
}
}
@@ -1701,6 +1714,11 @@ quit (void)
return signal_or_quit (Qquit, Qnil, true);
}
+/* Has an error in redisplay giving rise to a backtrace occurred as
+ yet in the current command? This gets reset in the command
+ loop. */
+bool backtrace_yet = false;
+
/* Signal an error, or quit. ERROR_SYMBOL and DATA are as with Fsignal.
If KEYBOARD_QUIT, this is a quit; ERROR_SYMBOL should be
Qquit and DATA should be Qnil, and this function may return.
@@ -1816,6 +1834,40 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
unbind_to (count, Qnil);
}
+ /* If an error is signalled during a Lisp hook in redisplay, write a
+ backtrace into the buffer *Redisplay-trace*. */
+ if (!debugger_called && !NILP (error_symbol)
+ && backtrace_on_redisplay_error
+ && (NILP (clause) || h == redisplay_deep_handler)
+ && NILP (Vinhibit_debugger)
+ && !NILP (Ffboundp (Qdebug_early)))
+ {
+ max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
+ specpdl_ref count = SPECPDL_INDEX ();
+ ptrdiff_t counti = specpdl_ref_to_count (count);
+ 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;
+ max_ensure_room (&max_specpdl_size, counti, 200);
+ redisplay_trace_buffer = Fget_buffer_create (redisplay_trace, Qnil);
+ current_buffer = XBUFFER (redisplay_trace_buffer);
+ if (!backtrace_yet) /* Are we on the first backtrace of the command? */
+ Ferase_buffer ();
+ else
+ Finsert (1, &gap);
+ backtrace_yet = true;
+ specbind (Qstandard_output, redisplay_trace_buffer);
+ specbind (Qdebugger, Qdebug_early);
+ 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);
+
+ Vdelayed_warnings_list = Fcons (list2 (Qerror, delayed_warning),
+ Vdelayed_warnings_list);
+ }
+
if (!NILP (clause))
{
Lisp_Object unwind_data
@@ -4278,6 +4330,11 @@ Does not apply if quit is handled by a `condition-case'. */);
DEFVAR_BOOL ("debug-on-next-call", debug_on_next_call,
doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */);
+ DEFVAR_BOOL ("backtrace-on-redisplay-error", backtrace_on_redisplay_error,
+ doc: /* Non-nil means create a backtrace if a lisp error occurs in redisplay.
+The backtrace is written to buffer *Redisplay-trace*. */);
+ backtrace_on_redisplay_error = false;
+
DEFVAR_BOOL ("debugger-may-continue", debugger_may_continue,
doc: /* Non-nil means debugger may continue execution.
This is nil when the debugger is called under circumstances where it
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 119ec284094..e089f9dea85 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -677,7 +677,11 @@ ftcrhbfont_begin_hb_font (struct font *font, double *position_unit)
ftcrfont_info->ft_size = ft_face->size;
hb_font_t *hb_font = fthbfont_begin_hb_font (font, position_unit);
- if (ftcrfont_info->bitmap_position_unit)
+ /* HarfBuzz 5 correctly scales bitmap-only fonts without position
+ unit adjustment.
+ (https://github.com/harfbuzz/harfbuzz/issues/489) */
+ if (!hb_version_atleast (5, 0, 0)
+ && ftcrfont_info->bitmap_position_unit)
*position_unit = ftcrfont_info->bitmap_position_unit;
return hb_font;
diff --git a/src/indent.c b/src/indent.c
index d2dfaee254e..cb368024d97 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -306,8 +306,8 @@ and point (e.g., control characters will have a width of 2 or 4, tabs
will have a variable width).
Ignores finite width of frame, which means that this function may return
values greater than (frame-width).
-In a buffer with very long lines, the value can be zero, because calculating
-the exact number is very expensive.
+In a buffer with very long lines, the value will be an approximation,
+because calculating the exact number is very expensive.
Whether the line is visible (if `selective-display' is t) has no effect;
however, ^M is treated as end of line when `selective-display' is t.
Text that has an invisible property is considered as having width 0, unless
@@ -316,8 +316,6 @@ Text that has an invisible property is considered as having width 0, unless
{
Lisp_Object temp;
- if (current_buffer->long_line_optimizations_p)
- return make_fixnum (0);
XSETFASTINT (temp, current_column ());
return temp;
}
@@ -346,6 +344,14 @@ current_column (void)
&& MODIFF == last_known_column_modified)
return last_known_column;
+ ptrdiff_t line_beg = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1,
+ NULL, NULL, 1);
+
+ /* Avoid becoming abysmally slow for very long lines. */
+ if (current_buffer->long_line_optimizations_p
+ && !NILP (Vlong_line_threshold)
+ && PT - line_beg > XFIXNUM (Vlong_line_threshold))
+ return PT - line_beg; /* this is an approximation! */
/* If the buffer has overlays, text properties,
or multibyte characters, use a more general algorithm. */
if (buffer_intervals (current_buffer)
@@ -561,13 +567,53 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol,
ptrdiff_t scan, scan_byte, next_boundary, prev_pos, prev_bpos;
scan = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &scan_byte, 1);
- next_boundary = scan;
- prev_pos = scan;
- prev_bpos = scan_byte;
window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
w = ! NILP (window) ? XWINDOW (window) : NULL;
+ if (current_buffer->long_line_optimizations_p)
+ {
+ bool lines_truncated = false;
+
+ if (!NILP (BVAR (current_buffer, truncate_lines)))
+ lines_truncated = true;
+ else if (w && FIXNUMP (Vtruncate_partial_width_windows))
+ lines_truncated =
+ w->total_cols < XFIXNAT (Vtruncate_partial_width_windows);
+ else if (w && !NILP (Vtruncate_partial_width_windows))
+ lines_truncated =
+ w->total_cols < FRAME_COLS (XFRAME (WINDOW_FRAME (w)));
+ /* Special optimization for buffers with long and truncated
+ lines: assumes that each character is a single column. */
+ if (lines_truncated)
+ {
+ ptrdiff_t bolpos = scan;
+ /* The newline which ends this line or ZV. */
+ ptrdiff_t eolpos =
+ find_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, NULL, NULL, 1);
+
+ scan = bolpos + goal;
+ if (scan > end)
+ scan = end;
+ if (scan > eolpos)
+ scan = (eolpos == ZV ? ZV : eolpos - 1);
+ col = scan - bolpos;
+ if (col > large_hscroll_threshold)
+ {
+ prev_col = col - 1;
+ prev_pos = scan - 1;
+ prev_bpos = CHAR_TO_BYTE (scan);
+ goto endloop;
+ }
+ /* Restore the values we've overwritten above. */
+ scan = bolpos;
+ col = 0;
+ }
+ }
+ next_boundary = scan;
+ prev_pos = scan;
+ prev_bpos = scan_byte;
+
memset (&cmp_it, 0, sizeof cmp_it);
cmp_it.id = -1;
composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil);
diff --git a/src/keyboard.c b/src/keyboard.c
index 4ad6e4e6bd1..8a2b7d58c4b 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1331,6 +1331,7 @@ command_loop_1 (void)
display_malloc_warning ();
Vdeactivate_mark = Qnil;
+ backtrace_yet = false;
/* Don't ignore mouse movements for more than a single command
loop. (This flag is set in xdisp.c whenever the tool bar is
@@ -1841,7 +1842,7 @@ safe_run_hooks_1 (ptrdiff_t nargs, Lisp_Object *args)
static Lisp_Object
safe_run_hooks_error (Lisp_Object error, ptrdiff_t nargs, Lisp_Object *args)
{
- eassert (nargs == 2);
+ eassert (nargs >= 2 && nargs <= 4);
AUTO_STRING (format, "Error in %s (%S): %S");
Lisp_Object hook = args[0];
Lisp_Object fun = args[1];
@@ -1915,6 +1916,17 @@ safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
unbind_to (count, Qnil);
}
+void
+safe_run_hooks_2 (Lisp_Object hook, Lisp_Object arg1, Lisp_Object arg2)
+{
+ specpdl_ref count = SPECPDL_INDEX ();
+
+ specbind (Qinhibit_quit, Qt);
+ run_hook_with_args (4, ((Lisp_Object []) {hook, hook, arg1, arg2}),
+ safe_run_hook_funcall);
+ unbind_to (count, Qnil);
+}
+
/* Nonzero means polling for input is temporarily suppressed. */
@@ -12638,10 +12650,17 @@ cancels any modification. */);
DEFSYM (Qdeactivate_mark, "deactivate-mark");
DEFVAR_LISP ("deactivate-mark", Vdeactivate_mark,
- doc: /* If an editing command sets this to t, deactivate the mark afterward.
+ doc: /* Whether to deactivate the mark after an editing command.
The command loop sets this to nil before each command,
and tests the value when the command returns.
-Buffer modification stores t in this variable. */);
+If an editing command sets this non-nil, deactivate the mark after
+the command returns.
+
+Buffer modifications store t in this variable.
+
+By default, deactivating the mark will save the contents of the region
+according to `select-active-regions', unless this is set to the symbol
+`dont-save'. */);
Vdeactivate_mark = Qnil;
Fmake_variable_buffer_local (Qdeactivate_mark);
diff --git a/src/lisp.h b/src/lisp.h
index fe6e98843d1..2f73ba4c617 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4530,6 +4530,7 @@ extern Lisp_Object Vrun_hooks;
extern Lisp_Object Vsignaling_function;
extern Lisp_Object inhibit_lisp_code;
extern bool signal_quit_p (Lisp_Object);
+extern bool backtrace_yet;
/* To run a normal hook, use the appropriate function from the list below.
The calling convention:
@@ -4831,6 +4832,7 @@ extern bool detect_input_pending_ignore_squeezables (void);
extern bool detect_input_pending_run_timers (bool);
extern void safe_run_hooks (Lisp_Object);
extern void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
+extern void safe_run_hooks_2 (Lisp_Object, Lisp_Object, Lisp_Object);
extern void cmd_error_internal (Lisp_Object, const char *);
extern Lisp_Object command_loop_2 (Lisp_Object);
extern Lisp_Object read_menu_command (void);
diff --git a/src/timefns.c b/src/timefns.c
index 1112f174763..eed2edf1cc0 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -401,6 +401,10 @@ decode_float_time (double t, struct lisp_time *result)
else
{
int scale = double_integer_scale (t);
+ /* FIXME: `double_integer_scale` often returns values that are
+ "pessimistic" (i.e. larger than necessary), so 3.5 gets converted
+ to (7881299347898368 . 2251799813685248) rather than (7 . 2).
+ On 64bit systems, this should not matter very much, tho. */
eassume (scale < flt_radix_power_size);
if (scale < 0)
@@ -818,17 +822,6 @@ decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
if (NILP (specified_time))
form = TIMEFORM_NIL;
- else if (FLOATP (specified_time))
- {
- double d = XFLOAT_DATA (specified_time);
- if (!isfinite (d))
- time_error (isnan (d) ? EDOM : EOVERFLOW);
- if (result)
- decode_float_time (d, result);
- else
- *dresult = d;
- return TIMEFORM_FLOAT;
- }
else if (CONSP (specified_time))
{
high = XCAR (specified_time);
@@ -868,6 +861,22 @@ decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
if (! INTEGERP (low))
form = TIMEFORM_INVALID;
}
+ else if (FASTER_TIMEFNS && INTEGERP (specified_time))
+ {
+ decode_ticks_hz (specified_time, make_fixnum (1), result, dresult);
+ return form;
+ }
+ else if (FLOATP (specified_time))
+ {
+ double d = XFLOAT_DATA (specified_time);
+ if (!isfinite (d))
+ time_error (isnan (d) ? EDOM : EOVERFLOW);
+ if (result)
+ decode_float_time (d, result);
+ else
+ *dresult = d;
+ return TIMEFORM_FLOAT;
+ }
int err = decode_time_components (form, high, low, usec, psec,
result, dresult);
@@ -1202,10 +1211,16 @@ time_cmp (Lisp_Object a, Lisp_Object b)
return 0;
/* Compare (X . Z) to (Y . Z) quickly if X and Y are fixnums.
- Do not inspect Z, as it is OK to not signal if A and B are invalid. */
- if (FASTER_TIMEFNS && CONSP (a) && CONSP (b) && BASE_EQ (XCDR (a), XCDR (b))
- && FIXNUMP (XCAR (a)) && FIXNUMP (XCAR (b)))
- return XFIXNUM (XCAR (a)) - XFIXNUM (XCAR (b));
+ Do not inspect Z, as it is OK to not signal if A and B are invalid.
+ Also, compare X to Y quickly if X and Y are fixnums. */
+ if (FASTER_TIMEFNS)
+ {
+ Lisp_Object x = a, y = b;
+ if (CONSP (a) && CONSP (b) && BASE_EQ (XCDR (a), XCDR (b)))
+ x = XCAR (a), y = XCAR (b);
+ if (FIXNUMP (x) && FIXNUMP (y))
+ return XFIXNUM (x) - XFIXNUM (y);
+ }
/* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing
ATICKS * BHZ to BTICKS * AHZ. */
@@ -1714,21 +1729,29 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
}
DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0,
- doc: /* Convert TIME value to a Lisp timestamp.
-With optional FORM, convert to that timestamp form.
+ doc: /* Convert TIME value to a Lisp timestamp of the given FORM.
Truncate the returned value toward minus infinity.
-If FORM is nil (the default), return the same form as `current-time'.
If FORM is a positive integer, return a pair of integers (TICKS . FORM),
where TICKS is the number of clock ticks and FORM is the clock frequency
-in ticks per second. If FORM is t, return (TICKS . PHZ), where
-PHZ is a suitable clock frequency in ticks per second. If FORM is
-`integer', return an integer count of seconds. If FORM is `list',
-return an integer list (HIGH LOW USEC PSEC), where HIGH has the most
-significant bits of the seconds, LOW has the least significant 16
-bits, and USEC and PSEC are the microsecond and picosecond counts. */)
+in ticks per second.
+
+If FORM is t, return (TICKS . PHZ), where PHZ is a suitable clock
+frequency in ticks per second.
+
+If FORM is `integer', return an integer count of seconds.
+
+If FORM is `list', return an integer list (HIGH LOW USEC PSEC), where
+HIGH has the most significant bits of the seconds, LOW has the least
+significant 16 bits, and USEC and PSEC are the microsecond and
+picosecond counts.
+
+If FORM is nil, the behavior depends on `current-time-list',
+but new code should not rely on it. */)
(Lisp_Object time, Lisp_Object form)
{
+ /* FIXME: Any reason why we don't offer a `float` output format option as
+ well, since we accept it as input? */
struct lisp_time t;
enum timeform input_form = decode_lisp_time (time, false, &t, 0);
if (NILP (form))
diff --git a/src/window.c b/src/window.c
index afb8f75537b..c8fcb3a607f 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6575,9 +6575,12 @@ and redisplay normally--don't erase and redraw the frame. */)
in case scroll_margin is buffer-local. */
this_scroll_margin = window_scroll_margin (w, MARGIN_IN_LINES);
- /* Don't use redisplay code for initial frames, as the necessary
- data structures might not be set up yet then. */
- if (!FRAME_INITIAL_P (XFRAME (w->frame)))
+ /* Don't use the display code for initial frames, as the necessary
+ data structures might not be set up yet then. Also don't use it
+ for buffers with very long lines, as it tremdously slows down
+ redisplay, especially when lines are truncated. */
+ if (!FRAME_INITIAL_P (XFRAME (w->frame))
+ && !current_buffer->long_line_optimizations_p)
{
specpdl_ref count = SPECPDL_INDEX ();
diff --git a/src/xdisp.c b/src/xdisp.c
index 1fcff2c2e3b..1e8f70b2db9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11040,6 +11040,15 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos)
int
partial_line_height (struct it *it_origin)
{
+ /* In a buffer with very long and truncated lines, we ignore the
+ possibly-partial height of the last line in the window: it is too
+ expensive to compute that (since in most cases that involves
+ going all the way to ZV), and the effect of ignoring it is
+ relatively minor. */
+ if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
+ && it_origin->line_wrap == TRUNCATE)
+ return 0;
+
int partial_height;
void *it_data = NULL;
struct it it;
@@ -11063,6 +11072,51 @@ partial_line_height (struct it *it_origin)
return partial_height;
}
+/* Approximate move_it_in_display_line_to for very long and truncated
+ display lines, when moving horizontally. This is used when the
+ buffer's long_line_optimizations_p flag is set. It ignores various
+ complications, like different font sizes, invisible text, display
+ and overlay strings, and, to some degree, bidirectional text. So
+ caveat emptor!
+
+ Starting from IT's position, reseat IT after skipping NCHARS
+ characters or to the next newline/ZV, whichever comes first. Return
+ what move_it_in_display_line_to would have returned in this case. */
+
+static enum move_it_result
+fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
+{
+ ptrdiff_t nl_bytepos;
+ ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
+ 1, &nl_bytepos);
+ struct text_pos new_pos;
+ enum move_it_result move_result;
+
+ if (nl_pos - IT_CHARPOS (*it) > nchars)
+ {
+ SET_TEXT_POS (new_pos,
+ IT_CHARPOS (*it) + nchars,
+ CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
+ move_result = MOVE_X_REACHED;
+ }
+ else
+ {
+ if (nl_bytepos < ZV_BYTE
+ || (nl_bytepos > BEGV_BYTE
+ && FETCH_BYTE (nl_bytepos - 1) == '\n'))
+ {
+ nl_pos--;
+ nl_bytepos--;
+ move_result = MOVE_NEWLINE_OR_CR;
+ }
+ else
+ move_result = MOVE_POS_MATCH_OR_ZV;
+ SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
+ }
+ reseat (it, new_pos, false);
+ return move_result;
+}
+
/* Return true if IT points into the middle of a display vector. */
bool
@@ -13106,8 +13160,7 @@ mode_line_update_needed (struct window *w)
{
return (w->column_number_displayed != -1
&& !(PT == w->last_point && !window_outdated (w))
- && (!current_buffer->long_line_optimizations_p
- && w->column_number_displayed != current_column ()));
+ && (w->column_number_displayed != current_column ()));
}
/* True if window start of W is frozen and may not be changed during
@@ -15776,7 +15829,20 @@ hscroll_window_tree (Lisp_Object window)
it.first_visible_x = window_hscroll_limited (w, it.f)
* FRAME_COLUMN_WIDTH (it.f);
it.last_visible_x = DISP_INFINITY;
- move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
+
+ ptrdiff_t nchars = pt - IT_CHARPOS (it);
+ if (current_buffer->long_line_optimizations_p
+ && nchars > large_hscroll_threshold)
+ {
+ /* Special optimization for very long and truncated
+ lines which need to be hscrolled far to the left:
+ jump directly to the (approximate) first position
+ that is visible, instead of slowly walking there. */
+ fast_move_it_horizontally (&it, nchars);
+ it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
+ }
+ else
+ move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
/* If the line ends in an overlay string with a newline,
we might infloop, because displaying the window will
want to put the cursor after the overlay, i.e. at X
@@ -15789,7 +15855,14 @@ hscroll_window_tree (Lisp_Object window)
if (hscl)
it.first_visible_x = (window_hscroll_limited (w, it.f)
* FRAME_COLUMN_WIDTH (it.f));
- move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
+ if (current_buffer->long_line_optimizations_p
+ && nchars > large_hscroll_threshold)
+ {
+ fast_move_it_horizontally (&it, nchars - 1);
+ it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
+ }
+ else
+ move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
}
current_buffer = saved_current_buffer;
@@ -16727,9 +16800,23 @@ redisplay_internal (void)
it.current_y = this_line_y;
it.vpos = this_line_vpos;
- /* The call to move_it_to stops in front of PT, but
- moves over before-strings. */
- move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+ if (current_buffer->long_line_optimizations_p
+ && it.line_wrap == TRUNCATE
+ && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
+ {
+ /* When lines are very long and truncated, jumping to
+ the next visible line is much faster than slowly
+ iterating there. */
+ reseat_at_next_visible_line_start (&it, false);
+ if (IT_CHARPOS (it) <= PT) /* point moved off this line */
+ it.vpos = this_line_vpos + 1;
+ }
+ else
+ {
+ /* The call to move_it_to stops in front of PT, but
+ moves over before-strings. */
+ move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+ }
if (it.vpos == this_line_vpos
&& (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
@@ -18119,8 +18206,8 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
{
specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
- run_hook_with_args_2 (Qwindow_scroll_functions, window,
- make_fixnum (CHARPOS (startp)));
+ 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. */
@@ -19229,6 +19316,16 @@ window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
return true;
}
+DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
+ 0, 0, 0,
+ doc: /* Return non-nil if long-line optimizations are in effect in current buffer.
+See `long-line-threshold' and `large-hscroll-threshold' for what these
+optimizations mean and when they are in effect. */)
+ (void)
+{
+ return current_buffer->long_line_optimizations_p ? Qt : Qnil;
+}
+
/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P means only
selected_window is redisplayed.
@@ -19504,33 +19601,36 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
ptrdiff_t it_charpos;
w->optional_new_start = false;
- start_display (&it, w, startp);
- move_it_to (&it, PT, 0, it.last_visible_y, -1,
- MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
- /* Record IT's position now, since line_bottom_y might change
- that. */
- it_charpos = IT_CHARPOS (it);
- /* Make sure we set the force_start flag only if the cursor row
- will be fully visible. Otherwise, the code under force_start
- label below will try to move point back into view, which is
- not what the code which sets optional_new_start wants. */
- if ((it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
- && !w->force_start)
- {
- if (it_charpos == PT)
- w->force_start = true;
- /* IT may overshoot PT if text at PT is invisible. */
- else if (it_charpos > PT && CHARPOS (startp) <= PT)
- w->force_start = true;
+ if (!w->force_start)
+ {
+ start_display (&it, w, startp);
+ move_it_to (&it, PT, 0, it.last_visible_y, -1,
+ MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+ /* Record IT's position now, since line_bottom_y might
+ change that. */
+ it_charpos = IT_CHARPOS (it);
+ /* Make sure we set the force_start flag only if the cursor
+ row will be fully visible. Otherwise, the code under
+ force_start label below will try to move point back into
+ view, which is not what the code which sets
+ optional_new_start wants. */
+ if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
+ {
+ if (it_charpos == PT)
+ w->force_start = true;
+ /* IT may overshoot PT if text at PT is invisible. */
+ else if (it_charpos > PT && CHARPOS (startp) <= PT)
+ w->force_start = true;
#ifdef GLYPH_DEBUG
- if (w->force_start)
- {
- if (window_frozen_p (w))
- debug_method_add (w, "set force_start from frozen window start");
- else
- debug_method_add (w, "set force_start from optional_new_start");
- }
+ if (w->force_start)
+ {
+ if (window_frozen_p (w))
+ debug_method_add (w, "set force_start from frozen window start");
+ else
+ debug_method_add (w, "set force_start from optional_new_start");
+ }
#endif
+ }
}
}
@@ -20256,7 +20356,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
|| w->base_line_pos > 0
/* Column number is displayed and different from the one displayed. */
|| (w->column_number_displayed != -1
- && !current_buffer->long_line_optimizations_p
&& (w->column_number_displayed != current_column ())))
/* This means that the window has a mode line. */
&& (window_wants_mode_line (w)
@@ -24496,8 +24595,26 @@ display_line (struct it *it, int cursor_vpos)
it->first_visible_x += x_incr;
it->last_visible_x += x_incr;
}
- move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
- MOVE_TO_POS | MOVE_TO_X);
+ if (current_buffer->long_line_optimizations_p
+ && it->line_wrap == TRUNCATE
+ && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
+ {
+ /* Special optimization for very long and truncated lines
+ which are hscrolled far to the left: jump directly to the
+ (approximate) position that is visible, instead of slowly
+ walking there. */
+ ptrdiff_t chars_to_skip =
+ it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
+ move_result = fast_move_it_horizontally (it, chars_to_skip);
+
+ if (move_result == MOVE_X_REACHED)
+ it->current_x = it->first_visible_x;
+ else /* use arbitrary value < first_visible_x */
+ it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
+ }
+ else
+ move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
+ MOVE_TO_POS | MOVE_TO_X);
/* If we are under a large hscroll, move_it_in_display_line_to
could hit the end of the line without reaching
first_visible_x. Pretend that we did reach it. This is
@@ -27758,17 +27875,6 @@ decode_mode_spec (struct window *w, register int c, int field_width,
even crash emacs.) */
if (mode_line_target == MODE_LINE_TITLE)
return "";
- else if (b->long_line_optimizations_p)
- {
- char *p = decode_mode_spec_buf;
- int pad = width - 2;
- while (pad-- > 0)
- *p++ = ' ';
- *p++ = '?';
- *p++ = '?';
- *p = '\0';
- return decode_mode_spec_buf;
- }
else
{
ptrdiff_t col = current_column ();
@@ -36112,6 +36218,7 @@ be let-bound around code that needs to disable messages temporarily. */);
defsubr (&Sbidi_find_overridden_directionality);
defsubr (&Sdisplay__line_is_continued_p);
defsubr (&Sget_display_property);
+ defsubr (&Slong_line_optimizations_p);
DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
diff --git a/src/xfns.c b/src/xfns.c
index 2845ecca6a9..6ed93ee42ca 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -6851,17 +6851,16 @@ The coordinates X and Y are interpreted in pixels relative to a position
#ifdef HAVE_XINPUT2
int deviceid;
- if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ deviceid = FRAME_DISPLAY_INFO (f)->client_pointer_device;
+
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2
+ && deviceid != -1)
{
- XGrabServer (FRAME_X_DISPLAY (f));
- if (XIGetClientPointer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- &deviceid))
- {
- XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
- FRAME_DISPLAY_INFO (f)->root_window,
- 0, 0, 0, 0, xval, yval);
- }
- XUngrabServer (FRAME_X_DISPLAY (f));
+ x_catch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
+ XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
+ FRAME_DISPLAY_INFO (f)->root_window,
+ 0, 0, 0, 0, xval, yval);
+ x_uncatch_errors_for_lisp (FRAME_DISPLAY_INFO (f));
}
else
#endif
diff --git a/src/xterm.c b/src/xterm.c
index ab43a8ec517..5047f3066be 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1398,6 +1398,15 @@ static int x_dnd_last_tooltip_x, x_dnd_last_tooltip_y;
/* Whether or not those values are actually known yet. */
static bool x_dnd_last_tooltip_valid;
+#ifdef HAVE_XINPUT2
+/* The master pointer device being used for the drag-and-drop
+ operation. */
+static int x_dnd_pointer_device;
+
+/* The keyboard device attached to that pointer device. */
+static int x_dnd_keyboard_device;
+#endif
+
/* Structure describing a single window that can be the target of
drag-and-drop operations. */
struct x_client_list_window
@@ -4705,6 +4714,67 @@ x_restore_events_after_dnd (struct frame *f, XWindowAttributes *wa)
dpyinfo->Xatom_XdndTypeList);
}
+#ifdef HAVE_XINPUT2
+
+/* Cancel the current drag-and-drop operation, sending leave messages
+ to any relevant toplevels. This is called from the event loop when
+ an event is received telling Emacs to gracefully cancel the
+ drag-and-drop operation. */
+
+static void
+x_dnd_cancel_dnd_early (void)
+{
+ struct frame *f;
+ xm_drop_start_message dmsg;
+
+ eassert (x_dnd_frame && x_dnd_in_progress);
+
+ f = x_dnd_frame;
+
+ if (x_dnd_last_seen_window != None
+ && x_dnd_last_protocol_version != -1)
+ x_dnd_send_leave (x_dnd_frame,
+ x_dnd_last_seen_window);
+ else if (x_dnd_last_seen_window != None
+ && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style)
+ && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE
+ && x_dnd_motif_setup_p)
+ {
+ dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR,
+ XM_DRAG_REASON_DROP_START);
+ dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST;
+ dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time;
+ dmsg.side_effects
+ = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f),
+ x_dnd_wanted_action),
+ XM_DROP_SITE_VALID, x_dnd_motif_operations,
+ XM_DROP_ACTION_DROP_CANCEL);
+ dmsg.x = 0;
+ dmsg.y = 0;
+ dmsg.index_atom = x_dnd_motif_atom;
+ dmsg.source_window = FRAME_X_WINDOW (f);
+
+ x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f,
+ x_dnd_last_seen_window,
+ FRAME_DISPLAY_INFO (f)->last_user_time);
+ xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f),
+ x_dnd_last_seen_window, &dmsg);
+ }
+
+ x_dnd_last_seen_window = None;
+ x_dnd_last_seen_toplevel = None;
+ x_dnd_in_progress = false;
+ x_dnd_waiting_for_finish = false;
+ x_dnd_return_frame_object = NULL;
+ x_dnd_movement_frame = NULL;
+ x_dnd_wheel_frame = NULL;
+ x_dnd_frame = NULL;
+ x_dnd_action = None;
+ x_dnd_action_symbol = Qnil;
+}
+
+#endif
+
static void
x_dnd_cleanup_drag_and_drop (void *frame)
{
@@ -11909,6 +11979,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
struct x_display_info *event_display;
#endif
unsigned int additional_mask;
+#ifdef HAVE_XINPUT2
+ struct xi_device_t *device;
+#endif
base = SPECPDL_INDEX ();
@@ -12089,6 +12162,33 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
x_dnd_wheel_frame = NULL;
x_dnd_init_type_lists = false;
x_dnd_need_send_drop = false;
+
+#ifdef HAVE_XINPUT2
+
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ {
+ /* Only accept input from the last master pointer to have interacted
+ with Emacs. This prevents another pointer device getting our
+ idea of the button state messed up. */
+ if (FRAME_DISPLAY_INFO (f)->client_pointer_device != -1)
+ x_dnd_pointer_device
+ = FRAME_DISPLAY_INFO (f)->client_pointer_device;
+ else
+ /* This returns Bool but cannot actually fail. */
+ XIGetClientPointer (FRAME_X_DISPLAY (f), None,
+ &x_dnd_pointer_device);
+
+ x_dnd_keyboard_device = -1;
+
+ device = xi_device_from_id (FRAME_DISPLAY_INFO (f),
+ x_dnd_pointer_device);
+
+ if (device)
+ x_dnd_keyboard_device = device->attachment;
+ }
+
+#endif
+
#ifdef HAVE_XKB
x_dnd_keyboard_state = 0;
@@ -12882,6 +12982,13 @@ xi_disable_devices (struct x_display_info *dpyinfo,
{
if (to_disable[j] == dpyinfo->devices[i].device_id)
{
+ if (x_dnd_in_progress
+ /* If the drag-and-drop pointer device is being
+ disabled, then cancel the drag and drop
+ operation. */
+ && to_disable[j] == x_dnd_pointer_device)
+ x_dnd_cancel_dnd_early ();
+
/* Free any scroll valuators that might be on this
device. */
#ifdef HAVE_XINPUT2_1
@@ -14164,11 +14271,13 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
ev->window = FRAME_X_WINDOW (f);
ev->format = 32;
- /* A 32-bit X client on a 64-bit X server can pass a window pointer
- as-is. A 64-bit client on a 32-bit X server is in trouble
- because a pointer does not fit and would be truncated while
- passing through the server. So use two slots and hope that X12
- will resolve such issues someday. */
+ /* A 32-bit X client can pass a window pointer through the X server
+ as-is.
+
+ A 64-bit client is in trouble because a pointer does not fit in
+ the 32 bits given for ClientMessage data and will be truncated by
+ Xlib. So use two slots and hope that X12 will resolve such
+ issues someday. */
ev->data.l[0] = iw >> 31 >> 1;
ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
ev->data.l[2] = part;
@@ -17316,6 +17425,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
union buffered_input_event inev;
int count = 0;
int do_help = 0;
+#ifdef HAVE_XINPUT2
+ struct xi_device_t *gen_help_device;
+ Time gen_help_time;
+#endif
ptrdiff_t nbytes = 0;
struct frame *any, *f = NULL;
Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
@@ -17345,6 +17458,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
EVENT_INIT (inev.ie);
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
+#ifdef HAVE_XINPUT2
+ gen_help_device = NULL;
+#endif
/* Ignore events coming from various extensions, such as XFIXES and
XKB. */
@@ -17870,6 +17986,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!x_window_to_frame (dpyinfo, event->xselection.requestor))
goto OTHER;
#endif /* not USE_X_TOOLKIT and not USE_GTK */
+#ifdef HAVE_GTK3
+ /* GTK 3 apparently chokes on these events since they have no
+ associated device. (bug#56869, another bug as well that I
+ can't find) */
+ *finish = X_EVENT_DROP;
+#endif
x_handle_selection_notify (&event->xselection);
break;
@@ -17878,6 +18000,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!x_window_to_frame (dpyinfo, event->xselectionclear.window))
goto OTHER;
#endif /* not USE_X_TOOLKIT and not USE_GTK */
+#ifdef HAVE_GTK3
+ *finish = X_EVENT_DROP;
+#endif
{
const XSelectionClearEvent *eventp = &event->xselectionclear;
@@ -17904,6 +18029,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
goto OTHER;
#endif /* USE_X_TOOLKIT */
+#ifdef HAVE_GTK3
+ *finish = X_EVENT_DROP;
+#endif
{
const XSelectionRequestEvent *eventp = &event->xselectionrequest;
@@ -18446,6 +18574,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#endif
if (x_dnd_in_progress
+ /* When _NET_WM_CLIENT_LIST stacking is being used, changes
+ in that property are watched for, and it's not necessary
+ to update the state in response to ordinary window
+ substructure events. */
+ && !x_dnd_use_toplevels
&& dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
@@ -20280,6 +20413,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case CirculateNotify:
if (x_dnd_in_progress
+ /* When _NET_WM_CLIENT_LIST stacking is being used, changes
+ in that property are watched for, and it's not necessary
+ to update the state in response to ordinary window
+ substructure events. */
+ && !x_dnd_use_toplevels
&& dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
x_dnd_update_state (dpyinfo, dpyinfo->last_user_time);
goto OTHER;
@@ -20876,6 +21014,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
operation, don't send an event. We only have
to set the user time. */
if (x_dnd_in_progress
+ /* If another master device moved the
+ pointer, we should put a wheel event on
+ the keyboard buffer as usual. It will be
+ run once the drag-and-drop operation
+ completes. */
+ && xev->deviceid == x_dnd_pointer_device
&& (command_loop_level + minibuf_level
<= x_dnd_recursion_depth)
&& dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
@@ -20968,6 +21112,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
`x-dnd-movement-function`. */
&& (command_loop_level + minibuf_level
<= x_dnd_recursion_depth)
+ && xev->deviceid == x_dnd_pointer_device
&& dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
{
Window target, toplevel;
@@ -21270,7 +21415,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
has changed, generate a HELP_EVENT. */
if (!NILP (help_echo_string)
|| !NILP (previous_help_echo_string))
- do_help = 1;
+ {
+ /* Also allow the focus and client pointer to be
+ adjusted accordingly, in case a help tooltip is
+ shown. */
+ gen_help_device = device;
+ gen_help_time = xev->time;
+
+ do_help = 1;
+ }
goto XI_OTHER;
}
@@ -21294,6 +21447,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (x_dnd_in_progress
&& (command_loop_level + minibuf_level
<= x_dnd_recursion_depth)
+ && xev->deviceid == x_dnd_pointer_device
&& dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
{
f = mouse_or_wdesc_frame (dpyinfo, xev->event);
@@ -21333,6 +21487,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
+ if (f && device)
+ xi_handle_interaction (dpyinfo, f, device,
+ xev->time);
+
if (xev->evtype == XI_ButtonPress
&& x_dnd_last_seen_window != None)
{
@@ -21579,11 +21737,19 @@ handle_one_xevent (struct x_display_info *dpyinfo,
xev->send_event);
source = xi_device_from_id (dpyinfo, xev->sourceid);
+ device = xi_device_from_id (dpyinfo, xev->deviceid);
#ifdef HAVE_XWIDGETS
xvw = xwidget_view_from_window (xev->event);
if (xvw)
{
+ /* If the user interacts with a frame that's focused
+ on another device, but not the current focus
+ frame, make it the focus frame. */
+ if (device)
+ xi_handle_interaction (dpyinfo, xvw->frame,
+ device, xev->time);
+
xwidget_button (xvw, xev->evtype == XI_ButtonPress,
lrint (xev->event_x), lrint (xev->event_y),
xev->detail, xi_convert_event_state (xev),
@@ -21603,8 +21769,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
- device = xi_device_from_id (dpyinfo, xev->deviceid);
-
if (!device)
goto XI_OTHER;
@@ -22162,7 +22326,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state);
#ifdef XK_F1
- if (x_dnd_in_progress && keysym == XK_F1)
+ if (x_dnd_in_progress
+ && xev->deviceid == x_dnd_keyboard_device
+ && keysym == XK_F1)
{
x_dnd_xm_use_help = true;
goto xi_done_keysym;
@@ -22426,11 +22592,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case XI_HierarchyChanged:
{
- XIHierarchyEvent *hev = (XIHierarchyEvent *) xi_event;
+ XIHierarchyEvent *hev;
XIDeviceInfo *info;
int i, ndevices, n_disabled, *disabled;
struct xi_device_t *device;
+ bool any_changed;
+ any_changed = false;
+ hev = (XIHierarchyEvent *) xi_event;
disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info);
n_disabled = 0;
@@ -22440,8 +22609,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
/* Handle all disabled devices now, to prevent
things happening out-of-order later. */
- xi_disable_devices (dpyinfo, disabled, n_disabled);
- n_disabled = 0;
+
+ if (ndevices)
+ {
+ xi_disable_devices (dpyinfo, disabled, n_disabled);
+ n_disabled = 0;
+
+ /* This flag really just means that disabled
+ devices were handled early and should be
+ used in conjunction with n_disabled. */
+ any_changed = true;
+ }
x_catch_errors (dpyinfo->display);
info = XIQueryDevice (dpyinfo->display, hev->info[i].deviceid,
@@ -22492,9 +22670,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
event. */
xi_disable_devices (dpyinfo, disabled, n_disabled);
- /* Now that the device hierarchy has been changed,
- recompute focus. */
- xi_handle_focus_change (dpyinfo);
+ /* 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);
goto XI_OTHER;
}
@@ -23182,6 +23363,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (do_help > 0)
{
any_help_event_p = true;
+#ifdef HAVE_XINPUT2
+ if (gen_help_device)
+ xi_handle_interaction (dpyinfo, f,
+ gen_help_device,
+ gen_help_time);
+#endif
gen_help_event (help_echo_string, frame, help_echo_window,
help_echo_object, help_echo_pos);
}
@@ -25947,27 +26134,25 @@ x_set_window_size (struct frame *f, bool change_gravity,
void
frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
{
- block_input ();
#ifdef HAVE_XINPUT2
int deviceid;
- if (FRAME_DISPLAY_INFO (f)->supports_xi2)
+ deviceid = FRAME_DISPLAY_INFO (f)->client_pointer_device;
+
+ if (FRAME_DISPLAY_INFO (f)->supports_xi2
+ && deviceid != -1)
{
- if (XIGetClientPointer (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- &deviceid))
- {
- x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
- XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
- FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
- x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
- }
+ block_input ();
+ x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
+ XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
+ FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
+ x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
+ unblock_input ();
}
else
#endif
XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
0, 0, 0, 0, pix_x, pix_y);
- unblock_input ();
}
/* Raise frame F. */
@@ -28955,7 +29140,7 @@ void
x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
Lisp_Object current_owner)
{
- Lisp_Object tail, frame, new_owner, tem;
+ Lisp_Object tail, frame, new_owner;
Time timestamp;
Window *owners;
Atom *names;
@@ -28985,7 +29170,7 @@ x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
FOR_EACH_TAIL_SAFE (tail)
{
- tem = XCAR (tail);
+ Lisp_Object tem = XCAR (tail);
++nowners;
/* The selection is really lost (since we cannot find a new
@@ -29019,7 +29204,7 @@ x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
FOR_EACH_TAIL_SAFE (tail)
{
- tem = XCAR (tail);
+ Lisp_Object tem = XCAR (tail);
/* Now check if we still don't own that selection, which can
happen if another program set itself as the owner. */
@@ -29039,9 +29224,10 @@ x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
FOR_EACH_TAIL_SAFE (tail)
{
+ Lisp_Object tem = XCAR (tail);
+
reply = xcb_get_selection_owner_reply (dpyinfo->xcb_connection,
cookies[nowners++], &error);
-
if (reply)
owners[nowners - 1] = reply->owner;
else
@@ -29071,7 +29257,7 @@ x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost,
FOR_EACH_TAIL_SAFE (tail)
{
- tem = XCAR (tail);
+ Lisp_Object tem = XCAR (tail);
/* If the selection isn't owned by us anymore, note that the
selection was lost. */
diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el
index a655377e6cc..1a27467d292 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -570,7 +570,12 @@ Evaluate BODY for each created sequence.
(substring "2")
(substring "1"))))
(should (equal (seq-uniq list) '("1" "2" "3")))
- (should (equal (seq-uniq list #'eq) '("1" "2" "3" "2" "1")))))
+ (should (equal (seq-uniq list #'eq) '("1" "2" "3" "2" "1"))))
+ ;; Long lists have a different code path.
+ (let ((list (seq-map-indexed (lambda (_ i) i)
+ (make-list 10000 nil))))
+ (should (= (length list) 10000))
+ (should (= (length (seq-uniq (append list list))) 10000))))
(provide 'seq-tests)
;;; seq-tests.el ends here
diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el
new file mode 100644
index 00000000000..e86985ec717
--- /dev/null
+++ b/test/lisp/eshell/esh-cmd-tests.el
@@ -0,0 +1,283 @@
+;;; esh-cmd-tests.el --- esh-cmd test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's command invocation.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(defvar eshell-test-value nil)
+
+;;; Tests:
+
+
+;; Command invocation
+
+(ert-deftest esh-cmd-test/simple-command-result ()
+ "Test invocation with a simple command."
+ (should (equal (eshell-test-command-result "+ 1 2") 3)))
+
+(ert-deftest esh-cmd-test/lisp-command ()
+ "Test invocation with an elisp command."
+ (should (equal (eshell-test-command-result "(+ 1 2)") 3)))
+
+(ert-deftest esh-cmd-test/lisp-command-with-quote ()
+ "Test invocation with an elisp command containing a quote."
+ (should (equal (eshell-test-command-result "(eq 'foo nil)") nil)))
+
+(ert-deftest esh-cmd-test/lisp-command-args ()
+ "Test invocation with elisp and trailing args.
+Test that trailing arguments outside the S-expression are
+ignored. e.g. \"(+ 1 2) 3\" => 3"
+ (should (equal (eshell-test-command-result "(+ 1 2) 3") 3)))
+
+(ert-deftest esh-cmd-test/subcommand ()
+ "Test invocation with a simple subcommand."
+ (should (equal (eshell-test-command-result "{+ 1 2}") 3)))
+
+(ert-deftest esh-cmd-test/subcommand-args ()
+ "Test invocation with a subcommand and trailing args.
+Test that trailing arguments outside the subcommand are ignored.
+e.g. \"{+ 1 2} 3\" => 3"
+ (should (equal (eshell-test-command-result "{+ 1 2} 3") 3)))
+
+(ert-deftest esh-cmd-test/subcommand-lisp ()
+ "Test invocation with an elisp subcommand and trailing args.
+Test that trailing arguments outside the subcommand are ignored.
+e.g. \"{(+ 1 2)} 3\" => 3"
+ (should (equal (eshell-test-command-result "{(+ 1 2)} 3") 3)))
+
+
+;; Logical operators
+
+(ert-deftest esh-cmd-test/and-operator ()
+ "Test logical && operator."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-command-result-p "[ foo = foo ] && echo hi"
+ "hi\n")
+ (eshell-command-result-p "[ foo = bar ] && echo hi"
+ "\\`\\'")))
+
+(ert-deftest esh-cmd-test/or-operator ()
+ "Test logical || operator."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-command-result-p "[ foo = foo ] || echo hi"
+ "\\`\\'")
+ (eshell-command-result-p "[ foo = bar ] || echo hi"
+ "hi\n")))
+
+
+;; Control flow statements
+
+(ert-deftest esh-cmd-test/for-loop ()
+ "Test invocation of a for loop."
+ (with-temp-eshell
+ (eshell-command-result-p "for i in 5 { echo $i }"
+ "5\n")))
+
+(ert-deftest esh-cmd-test/for-loop-list ()
+ "Test invocation of a for loop iterating over a list."
+ (with-temp-eshell
+ (eshell-command-result-p "for i in (list 1 2 (list 3 4)) { echo $i }"
+ "1\n2\n(3 4)\n")))
+
+(ert-deftest esh-cmd-test/for-loop-multiple-args ()
+ "Test invocation of a for loop iterating over multiple arguments."
+ (with-temp-eshell
+ (eshell-command-result-p "for i in 1 2 (list 3 4) { echo $i }"
+ "1\n2\n3\n4\n")))
+
+(ert-deftest esh-cmd-test/for-name-loop () ; bug#15231
+ "Test invocation of a for loop using `name'."
+ (let ((process-environment (cons "name" process-environment)))
+ (should (equal (eshell-test-command-result
+ "for name in 3 { echo $name }")
+ 3))))
+
+(ert-deftest esh-cmd-test/for-name-shadow-loop () ; bug#15372
+ "Test invocation of a for loop using an env-var."
+ (let ((process-environment (cons "name=env-value" process-environment)))
+ (with-temp-eshell
+ (eshell-command-result-p
+ "echo $name; for name in 3 { echo $name }; echo $name"
+ "env-value\n3\nenv-value\n"))))
+
+(ert-deftest esh-cmd-test/while-loop ()
+ "Test invocation of a while loop."
+ (with-temp-eshell
+ (let ((eshell-test-value '(0 1 2)))
+ (eshell-command-result-p
+ (concat "while $eshell-test-value "
+ "{ setq eshell-test-value (cdr eshell-test-value) }")
+ "(1 2)\n(2)\n"))))
+
+(ert-deftest esh-cmd-test/while-loop-lisp-form ()
+ "Test invocation of a while loop using a Lisp form."
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-command-result-p
+ (concat "while (/= eshell-test-value 3) "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/while-loop-ext-cmd ()
+ "Test invocation of a while loop using an external command."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-command-result-p
+ (concat "while {[ $eshell-test-value -ne 3 ]} "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/until-loop ()
+ "Test invocation of an until loop."
+ (with-temp-eshell
+ (let ((eshell-test-value nil))
+ (eshell-command-result-p
+ (concat "until $eshell-test-value "
+ "{ setq eshell-test-value t }")
+ "t\n"))))
+
+(ert-deftest esh-cmd-test/until-loop-lisp-form ()
+ "Test invocation of an until loop using a Lisp form."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-command-result-p
+ (concat "until (= eshell-test-value 3) "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/until-loop-ext-cmd ()
+ "Test invocation of an until loop using an external command."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (let ((eshell-test-value 0))
+ (eshell-command-result-p
+ (concat "until {[ $eshell-test-value -eq 3 ]} "
+ "{ setq eshell-test-value (1+ eshell-test-value) }")
+ "1\n2\n3\n"))))
+
+(ert-deftest esh-cmd-test/if-statement ()
+ "Test invocation of an if statement."
+ (with-temp-eshell
+ (let ((eshell-test-value t))
+ (eshell-command-result-p "if $eshell-test-value {echo yes}"
+ "yes\n"))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-p "if $eshell-test-value {echo yes}"
+ "\\`\\'"))))
+
+(ert-deftest esh-cmd-test/if-else-statement ()
+ "Test invocation of an if/else statement."
+ (with-temp-eshell
+ (let ((eshell-test-value t))
+ (eshell-command-result-p "if $eshell-test-value {echo yes} {echo no}"
+ "yes\n"))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-p "if $eshell-test-value {echo yes} {echo no}"
+ "no\n"))))
+
+(ert-deftest esh-cmd-test/if-else-statement-lisp-form ()
+ "Test invocation of an if/else statement using a Lisp form."
+ (with-temp-eshell
+ (eshell-command-result-p "if (zerop 0) {echo yes} {echo no}"
+ "yes\n")
+ (eshell-command-result-p "if (zerop 1) {echo yes} {echo no}"
+ "no\n")
+ (let ((debug-on-error nil))
+ (eshell-command-result-p "if (zerop \"foo\") {echo yes} {echo no}"
+ "no\n"))))
+
+(ert-deftest esh-cmd-test/if-else-statement-lisp-form-2 ()
+ "Test invocation of an if/else statement using a Lisp form.
+This tests when `eshell-lisp-form-nil-is-failure' is nil."
+ (let ((eshell-lisp-form-nil-is-failure nil))
+ (with-temp-eshell
+ (eshell-command-result-p "if (zerop 0) {echo yes} {echo no}"
+ "yes\n")
+ (eshell-command-result-p "if (zerop 1) {echo yes} {echo no}"
+ "yes\n")
+ (let ((debug-on-error nil))
+ (eshell-command-result-p "if (zerop \"foo\") {echo yes} {echo no}"
+ "no\n")))))
+
+(ert-deftest esh-cmd-test/if-else-statement-ext-cmd ()
+ "Test invocation of an if/else statement using an external command."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-command-result-p "if {[ foo = foo ]} {echo yes} {echo no}"
+ "yes\n")
+ (eshell-command-result-p "if {[ foo = bar ]} {echo yes} {echo no}"
+ "no\n")))
+
+(ert-deftest esh-cmd-test/unless-statement ()
+ "Test invocation of an unless statement."
+ (with-temp-eshell
+ (let ((eshell-test-value t))
+ (eshell-command-result-p "unless $eshell-test-value {echo no}"
+ "\\`\\'"))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-p "unless $eshell-test-value {echo no}"
+ "no\n"))))
+
+(ert-deftest esh-cmd-test/unless-else-statement ()
+ "Test invocation of an unless/else statement."
+ (with-temp-eshell
+ (let ((eshell-test-value t))
+ (eshell-command-result-p "unless $eshell-test-value {echo no} {echo yes}"
+ "yes\n"))
+ (let ((eshell-test-value nil))
+ (eshell-command-result-p "unless $eshell-test-value {echo no} {echo yes}"
+ "no\n"))))
+
+(ert-deftest esh-cmd-test/unless-else-statement-lisp-form ()
+ "Test invocation of an unless/else statement using a Lisp form."
+ (with-temp-eshell
+ (eshell-command-result-p "unless (zerop 0) {echo no} {echo yes}"
+ "yes\n")
+ (eshell-command-result-p "unless (zerop 1) {echo no} {echo yes}"
+ "no\n")
+ (let ((debug-on-error nil))
+ (eshell-command-result-p "unless (zerop \"foo\") {echo no} {echo yes}"
+ "no\n"))))
+
+(ert-deftest esh-cmd-test/unless-else-statement-ext-cmd ()
+ "Test invocation of an unless/else statement using an external command."
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-command-result-p "unless {[ foo = foo ]} {echo no} {echo yes}"
+ "yes\n")
+ (eshell-command-result-p "unless {[ foo = bar ]} {echo no} {echo yes}"
+ "no\n")))
+
+;; esh-cmd-tests.el ends here
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
index 54e701a6aab..0c094ee5a79 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -500,18 +500,75 @@ inside double-quotes"
(eshell-command-result-p "echo $INSIDE_EMACS[, 1]"
"eshell")))
+(ert-deftest esh-var-test/last-status-var-lisp-command ()
+ "Test using the \"last exit status\" ($?) variable with a Lisp command"
+ (with-temp-eshell
+ (eshell-command-result-p "zerop 0; echo $?"
+ "t\n0\n")
+ (eshell-command-result-p "zerop 1; echo $?"
+ "0\n")
+ (let ((debug-on-error nil))
+ (eshell-command-result-p "zerop foo; echo $?"
+ "1\n"))))
+
+(ert-deftest esh-var-test/last-status-var-lisp-form ()
+ "Test using the \"last exit status\" ($?) variable with a Lisp form"
+ (let ((eshell-lisp-form-nil-is-failure t))
+ (with-temp-eshell
+ (eshell-command-result-p "(zerop 0); echo $?"
+ "t\n0\n")
+ (eshell-command-result-p "(zerop 1); echo $?"
+ "2\n")
+ (let ((debug-on-error nil))
+ (eshell-command-result-p "(zerop \"foo\"); echo $?"
+ "1\n")))))
+
+(ert-deftest esh-var-test/last-status-var-lisp-form-2 ()
+ "Test using the \"last exit status\" ($?) variable with a Lisp form.
+This tests when `eshell-lisp-form-nil-is-failure' is nil."
+ (let ((eshell-lisp-form-nil-is-failure nil))
+ (with-temp-eshell
+ (eshell-command-result-p "(zerop 0); echo $?"
+ "0\n")
+ (eshell-command-result-p "(zerop 0); echo $?"
+ "0\n")
+ (let ((debug-on-error nil))
+ (eshell-command-result-p "(zerop \"foo\"); echo $?"
+ "1\n")))))
+
+(ert-deftest esh-var-test/last-status-var-ext-cmd ()
+ "Test using the \"last exit status\" ($?) variable with an external command"
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ (eshell-command-result-p "[ foo = foo ]; echo $?"
+ "0\n")
+ (eshell-command-result-p "[ foo = bar ]; echo $?"
+ "1\n")))
+
(ert-deftest esh-var-test/last-result-var ()
"Test using the \"last result\" ($$) variable"
(with-temp-eshell
(eshell-command-result-p "+ 1 2; + $$ 2"
"3\n5\n")))
-(ert-deftest esh-var-test/last-result-var2 ()
+(ert-deftest esh-var-test/last-result-var-twice ()
"Test using the \"last result\" ($$) variable twice"
(with-temp-eshell
(eshell-command-result-p "+ 1 2; + $$ $$"
"3\n6\n")))
+(ert-deftest esh-var-test/last-result-var-ext-cmd ()
+ "Test using the \"last result\" ($$) variable with an external command"
+ (skip-unless (executable-find "["))
+ (with-temp-eshell
+ ;; MS-DOS/MS-Windows have an external command 'format', which we
+ ;; don't want here.
+ (let ((eshell-prefer-lisp-functions t))
+ (eshell-command-result-p "[ foo = foo ]; format \"%s\" $$"
+ "t\n")
+ (eshell-command-result-p "[ foo = bar ]; format \"%s\" $$"
+ "nil\n"))))
+
(ert-deftest esh-var-test/last-result-var-split-indices ()
"Test using the \"last result\" ($$) variable with split indices"
(with-temp-eshell
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index 5dc18775485..8423500ea7d 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -36,59 +36,6 @@
;;; Tests:
-(ert-deftest eshell-test/simple-command-result ()
- "Test `eshell-command-result' with a simple command."
- (should (equal (eshell-test-command-result "+ 1 2") 3)))
-
-(ert-deftest eshell-test/lisp-command ()
- "Test `eshell-command-result' with an elisp command."
- (should (equal (eshell-test-command-result "(+ 1 2)") 3)))
-
-(ert-deftest eshell-test/lisp-command-with-quote ()
- "Test `eshell-command-result' with an elisp command containing a quote."
- (should (equal (eshell-test-command-result "(eq 'foo nil)") nil)))
-
-(ert-deftest eshell-test/for-loop ()
- "Test `eshell-command-result' with a for loop.."
- (let ((process-environment (cons "foo" process-environment)))
- (should (equal (eshell-test-command-result
- "for foo in 5 { echo $foo }") 5))))
-
-(ert-deftest eshell-test/for-name-loop () ;Bug#15231
- "Test `eshell-command-result' with a for loop using `name'."
- (let ((process-environment (cons "name" process-environment)))
- (should (equal (eshell-test-command-result
- "for name in 3 { echo $name }") 3))))
-
-(ert-deftest eshell-test/for-name-shadow-loop () ; bug#15372
- "Test `eshell-command-result' with a for loop using an env-var."
- (let ((process-environment (cons "name=env-value" process-environment)))
- (with-temp-eshell
- (eshell-command-result-p "echo $name; for name in 3 { echo $name }; echo $name"
- "env-value\n3\nenv-value\n"))))
-
-(ert-deftest eshell-test/lisp-command-args ()
- "Test `eshell-command-result' with elisp and trailing args.
-Test that trailing arguments outside the S-expression are
-ignored. e.g. \"(+ 1 2) 3\" => 3"
- (should (equal (eshell-test-command-result "(+ 1 2) 3") 3)))
-
-(ert-deftest eshell-test/subcommand ()
- "Test `eshell-command-result' with a simple subcommand."
- (should (equal (eshell-test-command-result "{+ 1 2}") 3)))
-
-(ert-deftest eshell-test/subcommand-args ()
- "Test `eshell-command-result' with a subcommand and trailing args.
-Test that trailing arguments outside the subcommand are ignored.
-e.g. \"{+ 1 2} 3\" => 3"
- (should (equal (eshell-test-command-result "{+ 1 2} 3") 3)))
-
-(ert-deftest eshell-test/subcommand-lisp ()
- "Test `eshell-command-result' with an elisp subcommand and trailing args.
-Test that trailing arguments outside the subcommand are ignored.
-e.g. \"{(+ 1 2)} 3\" => 3"
- (should (equal (eshell-test-command-result "{(+ 1 2)} 3") 3)))
-
(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"))
diff --git a/test/lisp/international/ucs-normalize-tests.el b/test/lisp/international/ucs-normalize-tests.el
index 27a4e70c78e..774a3ea7ec9 100644
--- a/test/lisp/international/ucs-normalize-tests.el
+++ b/test/lisp/international/ucs-normalize-tests.el
@@ -246,7 +246,7 @@ must be true for all conformant implementations:
ucs-normalize-tests--rule1-failing-for-partX
ucs-normalize-tests--rule1-holds-p
ucs-normalize-tests--rule2-holds-p))
- (or (byte-code-function-p (symbol-function fun))
+ (or (compiled-function-p (symbol-function fun))
(byte-compile fun)))
(let ((ucs-normalize-tests--chars-part1 (make-char-table 'ucs-normalize-tests t)))
(setq ucs-normalize-tests--part1-rule1-failed-lines
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index ad81d0c09ea..4dcf671f51f 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -7052,7 +7052,8 @@ This requires restrictions of file name syntax."
"银河系漫游指南系列"
"Автостопом по гала́ктике"
;; Use codepoints without a name. See Bug#31272.
- "™›šbung"
+ ;; Works on some Android systems only.
+ (unless (tramp--test-adb-p) "™›šbung")
;; Use codepoints from Supplementary Multilingual Plane (U+10000
;; to U+1FFFF).
"🌈🍒👋")