Compare commits

..

2 commits

Author SHA1 Message Date
Po Lu
a9e481e17f ChangeLog 2023-04-06 11:33:08 +08:00
Po Lu
ba4d3ef078 * No log message * 2023-04-06 11:31:41 +08:00
350 changed files with 7875 additions and 130163 deletions

View file

@ -21,9 +21,6 @@
(electric-quote-comment . nil) (electric-quote-comment . nil)
(electric-quote-string . nil) (electric-quote-string . nil)
(mode . bug-reference-prog))) (mode . bug-reference-prog)))
(c-ts-mode . ((c-ts-mode-indent-style . gnu)
(indent-tabs-mode . t)
(mode . bug-reference-prog)))
(log-edit-mode . ((log-edit-font-lock-gnu-style . t) (log-edit-mode . ((log-edit-font-lock-gnu-style . t)
(log-edit-setup-add-author . t) (log-edit-setup-add-author . t)
(vc-git-log-edit-summary-target-len . 50))) (vc-git-log-edit-summary-target-len . 50)))

View file

@ -321,7 +321,7 @@ them right the first time, so here are guidelines for formatting them:
** Committing your changes. ** Committing your changes.
When you commit changes, Git invokes several scripts that test the When you commit changes, Git invokes several scripts that test the
commit for validity, and may abort the commit if some of the tests commit for validity, and may abort the commit of some of the tests
fail. These scripts live in the '.git/hooks/' subdirectory of the fail. These scripts live in the '.git/hooks/' subdirectory of the
top-level directory of the repository, and they perform the following top-level directory of the repository, and they perform the following
tests: tests:

View file

@ -1,3 +1,8 @@
2023-04-06 Po Lu <luangruo@yahoo.com>
* configure.ac: Detect what is necessary to start incremental
GC.
2022-02-18 Stefan Kangas <stefankangas@gmail.com> 2022-02-18 Stefan Kangas <stefankangas@gmail.com>
* Version 28.3 released. * Version 28.3 released.

114348
ChangeLog.4

File diff suppressed because it is too large Load diff

View file

@ -417,9 +417,9 @@ advice-on-failure:
sanity-check: sanity-check:
@[ -f .no-advice-on-failure ] && exit 0; true @[ -f .no-advice-on-failure ] && exit 0; true
@v=`src/emacs${EXEEXT} --batch --eval \ @v=$$(src/emacs${EXEEXT} --batch --eval \
'(progn (defun f (n) (if (= 0 n) 1 (* n (f (- n 1))))) (princ (f 10)))' \ '(progn (defun f (n) (if (= 0 n) 1 (* n (f (- n 1))))) (princ (f 10)))' \
2> /dev/null`; \ 2> /dev/null); \
[ "X$$v" = "X3628800" ] && exit 0; \ [ "X$$v" = "X3628800" ] && exit 0; \
echo >&2 '***'; \ echo >&2 '***'; \
echo >&2 '*** '"\"make ${make-target}\" succeeded, but Emacs is not functional."; \ echo >&2 '*** '"\"make ${make-target}\" succeeded, but Emacs is not functional."; \
@ -1030,9 +1030,6 @@ $(foreach dir,$(distclean_dirs),$(eval $(call submake_template,$(dir),distclean)
distclean: $(distclean_dirs:=_distclean) clean-gsettings-schemas distclean: $(distclean_dirs:=_distclean) clean-gsettings-schemas
${top_distclean} ${top_distclean}
ifeq ($(HAVE_NATIVE_COMP),yes)
rm -rf native-lisp
endif
### 'bootstrap-clean' ### 'bootstrap-clean'
### Delete everything that can be reconstructed by 'make' and that ### Delete everything that can be reconstructed by 'make' and that
@ -1287,7 +1284,7 @@ PREFERRED_BRANCH = emacs-28
preferred-branch-is-current: preferred-branch-is-current:
git branch | grep -q '^\* $(PREFERRED_BRANCH)$$' git branch | grep -q '^\* $(PREFERRED_BRANCH)$$'
unchanged-history-files: unchanged-history-files:
x=`git diff-files --name-only $(CHANGELOG_N) $(emacslog)` && \ x=$$(git diff-files --name-only $(CHANGELOG_N) $(emacslog)) && \
test -z "$$x" test -z "$$x"
# Regular expression that matches the newest commit covered by a ChangeLog. # Regular expression that matches the newest commit covered by a ChangeLog.

View file

@ -182,7 +182,7 @@ files.")
("Philip Kaludercic" "Philip K\\." "Philip K") ("Philip Kaludercic" "Philip K\\." "Philip K")
("Philipp Stephani" "Philipp .*phst@google") ("Philipp Stephani" "Philipp .*phst@google")
("Piotr Zieliński" "Piotr Zielinski") ("Piotr Zieliński" "Piotr Zielinski")
("Po Lu" "Po Lu Via" "Your Name") ; looks like a mistake ("Po Lu" "Po Lu Via") ; looks like a mistake
("Przemysław Wojnowski" "Przemyslaw Wojnowski") ("Przemysław Wojnowski" "Przemyslaw Wojnowski")
("R. Bernstein" "rb@dustyfeet.com") ("R. Bernstein" "rb@dustyfeet.com")
("Rainer Schöpf" "Rainer Schoepf") ("Rainer Schöpf" "Rainer Schoepf")

View file

@ -181,7 +181,7 @@ ${charsetdir}/GB180304.map: ${charsetdir}/GB180302.map ${gb180304}
${AM_V_GEN}$(AWK) -f ${gb180304} < $< > $@ ${AM_V_GEN}$(AWK) -f ${gb180304} < $< > $@
${charsetdir}/JISX0201.map: ${GLIBC_CHARMAPS}/JIS_X0201.gz ${mapconv} ${compact} ${charsetdir}/JISX0201.map: ${GLIBC_CHARMAPS}/JIS_X0201.gz ${mapconv} ${compact}
${AM_V_GEN}(${run_mapconv} $< '/^<.*[ ]\/x[0-9]/' GLIBC-1 ${compact} && \ ${AM_V_GEN}(${mapconv} $< '/^<.*[ ]\/x[0-9]/' GLIBC-1 ${compact} && \
echo "# Generated by hand" && \ echo "# Generated by hand" && \
echo "0xA1-0xDF 0xFF61" ) > $@ echo "0xA1-0xDF 0xFF61" ) > $@

View file

@ -38,8 +38,7 @@
## So that eg [A-F] as used by KANJI-DATABASE branch below works as expected. ## So that eg [A-F] as used by KANJI-DATABASE branch below works as expected.
## Otherwise with LANG=en_US.utf8, CNS-6.map was generated with a ## Otherwise with LANG=en_US.utf8, CNS-6.map was generated with a
## bogus entry. By experiment, LC_COLLATE=C was not enough. ## bogus entry. By experiment, LC_COLLATE=C was not enough.
LC_ALL=C export LC_ALL=C
export LC_ALL
BASE=`expr "$1" : '.*/\(.*\)' '|' "$1"` # basename BASE=`expr "$1" : '.*/\(.*\)' '|' "$1"` # basename
FILE="admin/charsets/mapfiles/$BASE" FILE="admin/charsets/mapfiles/$BASE"

View file

@ -68,25 +68,16 @@ General steps (for each step, check for possible errors):
PREFERRED_BRANCH = emacs-NN PREFERRED_BRANCH = emacs-NN
where NN is the version on the release branch from which you are where NN is the version on the release branch from which you are
producing the tarball. If NN is incorrect (which it usually is producing the tarball. If NN is incorrect, update Makefile.in and
when starting a pretest of a new major release), update re-run 'configure' to update Makefile.
Makefile.in and re-run 'configure' to update Makefile.
For the first pretest of a new major release, consider starting a If the versioned ChangeLog.N file is too large, start a new one
new top-level ChangeLog.N file if the last versioned ChangeLog.N by bumping N, and also update the line in top-level Makefile.in
file is too large. A good point to start a new ChangeLog.N file which says
is when the last one gets larger than 1.5 MiB. If so, start a new
one by bumping N, and also update the line in top-level
Makefile.in which says
CHANGELOG_HISTORY_INDEX_MAX = N CHANGELOG_HISTORY_INDEX_MAX = N
by incrementing the value of N by 1; then regenerate Makefile. by incrementing the value of N by 1; then regenerate Makefile.
After bumping N, you need to actually create and commit
ChangeLog.N with the updated N, otherwise "M-x authors" below will
fail. The easiest way of creating the new ChangeLog.N is to
rename the file ChangeLog (without the .N suffix) left over from
the last major release (it is usually unversioned) and commit it.
Now: Now:
@ -108,12 +99,11 @@ General steps (for each step, check for possible errors):
the relevant entry. If a file was deleted or renamed, consider the relevant entry. If a file was deleted or renamed, consider
adding an appropriate entry to variables authors-ignored-files, adding an appropriate entry to variables authors-ignored-files,
authors-valid-file-names, or authors-renamed-files-alist in authors-valid-file-names, or authors-renamed-files-alist in
authors.el. If some authors are "ignored", consider adding authors.el.
entries to the author-aliases variable.
If necessary, repeat 'C-u M-x authors' after making those changes. If necessary, repeat 'C-u M-x authors' after making those changes.
Save the "*Authors*" buffer as etc/AUTHORS. Save the "*Authors*" buffer as etc/AUTHORS.
Check the diff looks reasonable. Maybe add more entries to Check the diff looks reasonable. Maybe add entries to
authors-ambiguous-files or authors-aliases, and repeat. authors-ambiguous-files or authors-aliases, and repeat.
Commit any fixes to authors.el. Commit any fixes to authors.el.
@ -179,13 +169,7 @@ General steps (for each step, check for possible errors):
messages from TeX, but those seem to be harmless, as the result messages from TeX, but those seem to be harmless, as the result
looks just fine.) looks just fine.)
5. Copy lisp/loaddefs.el to lisp/ldefs-boot.el. After copying, edit 5. Copy lisp/loaddefs.el to lisp/ldefs-boot.el.
ldefs-boot.el to add
;; no-byte-compile: t
to its file-local variables section, otherwise make-dist will
complain.
Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the files Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the files
changed by M-x set-version. Note that the set-version changes changed by M-x set-version. Note that the set-version changes

View file

@ -83,46 +83,6 @@ Lisp packages, Makefiles, scripts, and other software could determine
whether they run on emba by checking for the environment variable whether they run on emba by checking for the environment variable
EMACS_EMBA_CI. EMACS_EMBA_CI.
* Running Emba tests locally
As usual in GitLab, the tests run in containers, which could be
applied also locally. Unfortunately, the Emba container registry,
emba.gnu.org:5050, is not accessible publicly. Instead, the container
images must be build locally. Change the current directory to a
recent Emacs branch, and apply the command
docker build --target emacs-inotify --tag emacs-inotify \
-f test/infra/Dockerfile.emba .
This creates the Debian-based image emacs-inotify, based on the
instructions in the file Dockerfile.emba. This image is good for the
majority of tests. However, there are also other image build
instructions like emacs-filenotify-gio, emacs-eglot, emacs-gnustep and
emacs-native-comp-speed{0,1,2}. Use the appropriate one.
The image contains a directory "/checkout", which is a copy of your
local Emacs git repository. Emacs has been built in this directory
via "make bootstrap". In order to use the image, start a container
like
docker run --interactive --env EMACS_EMBA_CI=1 --name emacs-inotify \
emacs-inotify /bin/sh -i
In this container, change the current directory to "/checkout". Now
you can apply all commands known for Emacs, like
cd /checkout
make -C test files-tests.log
While this container runs, you can also access its filesystem from
your local Emacs via Tramp. For example, in order to see the result
of the above test run, open the log file in your local Emacs with
C-x C-f /docker:emacs-inotify:/checkout/test/lisp/files-tests.log
Note: On local Red Hat-based systems, use "podman" instead of "docker"
in the shell commands and Tramp file names.
This file is part of GNU Emacs. This file is part of GNU Emacs.

View file

@ -340,8 +340,7 @@ git_config diff.texinfo.xfuncname \
tailored_hooks= tailored_hooks=
sample_hooks= sample_hooks=
for hook in commit-msg pre-commit prepare-commit-msg post-commit \ for hook in commit-msg pre-commit prepare-commit-msg; do
pre-push commit-msg-files.awk; do
cmp -- build-aux/git-hooks/$hook "$hooks/$hook" >/dev/null 2>&1 || cmp -- build-aux/git-hooks/$hook "$hooks/$hook" >/dev/null 2>&1 ||
tailored_hooks="$tailored_hooks $hook" tailored_hooks="$tailored_hooks $hook"
done done

View file

@ -1,128 +0,0 @@
# Check the file list of GNU Emacs change log entries for each commit SHA.
# Copyright 2023 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
# GNU Emacs is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# GNU Emacs is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
### Commentary:
# This script accepts a list of (unabbreviated) Git commit SHAs, and
# will then iterate over them to check that any files mentioned in the
# commit message are actually present in the commit's diff. If not,
# it will print out the incorrect file names and return 1.
# You can also pass "-v reason=pre-push", which will add more-verbose
# output, indicating the abbreviated commit SHA and first line of the
# commit message for any improper commits.
### Code:
function get_commit_changes(commit_sha, changes, cmd, i, j, len, \
bits, filename) {
# Collect all the files touched in the specified commit.
cmd = ("git show --name-status --first-parent --format= " commit_sha)
while ((cmd | getline) > 0) {
for (i = 2; i <= NF; i++) {
len = split($i, bits, "/")
for (j = 1; j <= len; j++) {
if (j == 1)
filename = bits[j]
else
filename = filename "/" bits[j]
changes[filename] = 1
}
}
}
close(cmd)
}
function check_commit_msg_files(commit_sha, verbose, changes, good, \
cmd, msg, filenames_str, filenames, i) {
get_commit_changes(commit_sha, changes)
good = 1
cmd = ("git log -1 --format=%B " commit_sha)
while ((cmd | getline) > 0) {
if (verbose && ! msg)
msg = $0
# Find file entries in the commit message. We look at any line
# starting with "*" (possibly prefixed by "; ") followed by a ":",
# possibly on a different line. If we encounter a blank line
# without seeing a ":", then we don't treat that as a file entry.
# Accumulate the contents of a (possible) file entry.
if (/^[ \t]*$/)
filenames_str = ""
else if (/^(; )?\*[ \t]+[[:alnum:]]/)
filenames_str = $0
else if (filenames_str)
filenames_str = (filenames_str $0)
# We have a file entry; analyze it.
if (filenames_str && /:/) {
# Delete the leading "*" and any trailing information.
sub(/^(; )?\*[ \t]+/, "", filenames_str)
sub(/[ \t]*[[(<:].*$/, "", filenames_str)
# There might be multiple files listed in this entry, separated
# by spaces (and possibly a comma). Iterate over each of them.
split(filenames_str, filenames, ",[ \t]+")
for (i in filenames) {
# Remove trailing slashes from any directory entries.
sub(/\/$/, "", filenames[i])
if (length(filenames[i]) && ! (filenames[i] in changes)) {
if (good) {
# Print a header describing the error.
if (verbose)
printf("In commit %s \"%s\"...\n", substr(commit_sha, 1, 10), msg)
printf("Files listed in commit message, but not in diff:\n")
}
printf(" %s\n", filenames[i])
good = 0
}
}
filenames_str = ""
}
}
close(cmd)
return good
}
BEGIN {
if (reason == "pre-push")
verbose = 1
}
/^[a-z0-9]{40}$/ {
if (! check_commit_msg_files($0, verbose)) {
status = 1
}
}
END {
if (status != 0) {
if (reason == "pre-push")
error_msg = "Push aborted"
else
error_msg = "Bad commit message"
printf("%s; please see the file 'CONTRIBUTE'\n", error_msg)
}
exit status
}

View file

@ -1,47 +0,0 @@
#!/bin/sh
# Check the file list of GNU Emacs change log entries after committing.
# Copyright 2023 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
# GNU Emacs is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# GNU Emacs is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
### Commentary:
# This hook runs after a commit is finalized and checks that the files
# mentioned in the commit message match the diff. We perform this in
# the post-commit phase so that we can be sure we properly detect all
# the files in the diff (this is difficult during the commit-msg hook,
# since there's no cross-platform way to detect when a commit is being
# amended).
# However, since this is a post-commit hook, it's too late to error
# out and abort the commit: it's already done! As a result, this hook
# is purely advisory, and instead we error out when trying to push
# (see "pre-push" in this directory).
### Code:
HOOKS_DIR=`dirname "$0"`
# Prefer gawk if available, as it handles NUL bytes properly.
if type gawk >/dev/null 2>&1; then
awk="gawk"
else
awk="awk"
fi
git rev-parse HEAD | $awk -v reason=post-commit \
-f "$HOOKS_DIR"/commit-msg-files.awk

View file

@ -1,88 +0,0 @@
#!/bin/sh
# Check the file list of GNU Emacs change log entries before pushing.
# Copyright 2023 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
# GNU Emacs is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# GNU Emacs is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
### Commentary:
# This hook runs before pushing a series of commits and checks that
# the files mentioned in each commit message match the diffs. This
# helps ensure that the resulting change logs are correct, which
# should prevent errors when generating etc/AUTHORS.
# These checks also happen in the "post-commit" hook (which see), but
# that hook can't abort a commit; it just advises the committer to fix
# the commit so that this hook runs without errors.
### Code:
HOOKS_DIR=`dirname "$0"`
# Prefer gawk if available, as it handles NUL bytes properly.
if type gawk >/dev/null 2>&1; then
awk="gawk"
else
awk="awk"
fi
# Standard input receives lines of the form:
# <local ref> SP <local sha> SP <remote ref> SP <remote sha> LF
$awk -v origin_name="$1" '
# If the local SHA is all zeroes, ignore it.
$2 ~ /^0{40}$/ {
next
}
# Check any lines with a valid local SHA and whose remote ref is
# master or an emacs-NN release branch. (We want to avoid checking
# feature or scratch branches here.)
$2 ~ /^[a-z0-9]{40}$/ && $3 ~ /^refs\/heads\/(master|emacs-[0-9]+)$/ {
newref = $2
# If the remote SHA is all zeroes, this is a new object to be
# pushed (likely a branch)...
if ($4 ~ /^0{40}$/) {
back = 0
# ... Go backwards until we find a SHA on an origin branch.
# Stop trying after 1000 commits, just in case...
for (back = 0; back < 1000; back++) {
cmd = ("git branch -r -l '\''" origin_name "/*'\''" \
" --contains " newref "~" back)
rv = (cmd | getline)
close(cmd)
if (rv > 0)
break;
}
cmd = ("git rev-parse " newref "~" back)
cmd | getline oldref
if (!(oldref ~ /^[a-z0-9]{40}$/)) {
# The SHA is misformatted! Skip this line.
next
}
close(cmd)
} else if ($4 ~ /^[a-z0-9]{40}$/) {
oldref = $4
} else {
# The SHA is misformatted! Skip this line.
next
}
# Print every SHA after oldref, up to (and including) newref.
system("git rev-list --first-parent --reverse " oldref ".." newref)
}
' | $awk -v reason=pre-push -f "$HOOKS_DIR"/commit-msg-files.awk

View file

@ -527,6 +527,9 @@ OPTION_DEFAULT_OFF([be-app],
OPTION_DEFAULT_OFF([be-cairo], OPTION_DEFAULT_OFF([be-cairo],
[enable use of cairo under Haiku's Application Kit]) [enable use of cairo under Haiku's Application Kit])
OPTION_DEFAULT_OFF([incremental-gc],
[enable incremental garbage collector])
## Makefile.in needs the cache file name. ## Makefile.in needs the cache file name.
AC_SUBST([cache_file]) AC_SUBST([cache_file])
@ -1001,7 +1004,7 @@ AC_ARG_ENABLE([gcc-warnings],
# however, if there is also a .tarball-version file it is probably # however, if there is also a .tarball-version file it is probably
# just a release imported into Git for patch management. # just a release imported into Git for patch management.
gl_gcc_warnings=no gl_gcc_warnings=no
if test -d "$srcdir"/.git && test ! -f "$srcdir"/.tarball-version; then if test -e "$srcdir"/.git && test ! -f "$srcdir"/.tarball-version; then
# Clang typically identifies itself as GCC 4.2 or something similar # Clang typically identifies itself as GCC 4.2 or something similar
# even if it is recent enough to accept the warnings we enable. # even if it is recent enough to accept the warnings we enable.
AS_IF([test "$emacs_cv_clang" = yes], AS_IF([test "$emacs_cv_clang" = yes],
@ -1643,8 +1646,7 @@ case "$opsys" in
## Motif needs -lgen. ## Motif needs -lgen.
unixware) LIBS_SYSTEM="-lsocket -lnsl -lelf -lgen" ;; unixware) LIBS_SYSTEM="-lsocket -lnsl -lelf -lgen" ;;
# Haiku needs -lbsd for cfsetspeed. haiku) LIBS_SYSTEM="-lnetwork" ;;
haiku) LIBS_SYSTEM="-lnetwork -lbsd" ;;
esac esac
AC_SUBST([LIBS_SYSTEM]) AC_SUBST([LIBS_SYSTEM])
@ -2034,23 +2036,31 @@ if test "${with_ns}" != no; then
ns_appresdir=${ns_appdir}/Contents/Resources ns_appresdir=${ns_appdir}/Contents/Resources
ns_appsrc=Cocoa/Emacs.base ns_appsrc=Cocoa/Emacs.base
ns_fontfile=macfont.o ns_fontfile=macfont.o
elif flags=`(gnustep-config --objc-flags) 2>/dev/null`; then elif flags=$( (gnustep-config --objc-flags) 2>/dev/null); then
NS_IMPL_GNUSTEP=yes NS_IMPL_GNUSTEP=yes
NS_GNUSTEP_CONFIG=yes NS_GNUSTEP_CONFIG=yes
GNU_OBJC_CFLAGS="$flags" GNU_OBJC_CFLAGS="$flags"
LIBS_GNUSTEP=`gnustep-config --gui-libs || exit` LIBS_GNUSTEP=$(gnustep-config --gui-libs) || exit
elif test -f $GNUSTEP_CONFIG_FILE; then elif test -f $GNUSTEP_CONFIG_FILE; then
NS_IMPL_GNUSTEP=yes NS_IMPL_GNUSTEP=yes
dnl FIXME sourcing this several times in subshells seems inefficient. dnl FIXME sourcing this several times in subshells seems inefficient.
GNUSTEP_SYSTEM_HEADERS=`. $GNUSTEP_CONFIG_FILE \ GNUSTEP_SYSTEM_HEADERS=$(
&& AS_ECHO(["$GNUSTEP_SYSTEM_HEADERS"])` . $GNUSTEP_CONFIG_FILE
GNUSTEP_SYSTEM_LIBRARIES=` . $GNUSTEP_CONFIG_FILE \ AS_ECHO(["$GNUSTEP_SYSTEM_HEADERS"])
&& AS_ECHO(["$GNUSTEP_SYSTEM_LIBRARIES"])` )
GNUSTEP_SYSTEM_LIBRARIES=$(
. $GNUSTEP_CONFIG_FILE
AS_ECHO(["$GNUSTEP_SYSTEM_LIBRARIES"])
)
dnl I seemed to need these as well with GNUstep-startup 0.25. dnl I seemed to need these as well with GNUstep-startup 0.25.
GNUSTEP_LOCAL_HEADERS=`. $GNUSTEP_CONFIG_FILE \ GNUSTEP_LOCAL_HEADERS=$(
&& AS_ECHO(["$GNUSTEP_LOCAL_HEADERS"])` . $GNUSTEP_CONFIG_FILE
GNUSTEP_LOCAL_LIBRARIES=`. $GNUSTEP_CONFIG_FILE \ AS_ECHO(["$GNUSTEP_LOCAL_HEADERS"])
&& AS_ECHO(["$GNUSTEP_LOCAL_LIBRARIES"])` )
GNUSTEP_LOCAL_LIBRARIES=$(
. $GNUSTEP_CONFIG_FILE
AS_ECHO(["$GNUSTEP_LOCAL_LIBRARIES"])
)
test "x${GNUSTEP_LOCAL_HEADERS}" != "x" && \ test "x${GNUSTEP_LOCAL_HEADERS}" != "x" && \
GNUSTEP_LOCAL_HEADERS="-I${GNUSTEP_LOCAL_HEADERS}" GNUSTEP_LOCAL_HEADERS="-I${GNUSTEP_LOCAL_HEADERS}"
test "x${GNUSTEP_LOCAL_LIBRARIES}" != "x" && \ test "x${GNUSTEP_LOCAL_LIBRARIES}" != "x" && \
@ -3773,7 +3783,7 @@ if test "${HAVE_X11}" = "yes"; then
AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1], AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1],
[Define to 1 if libotf has OTF_get_variation_glyphs.]) [Define to 1 if libotf has OTF_get_variation_glyphs.])
fi fi
if $PKG_CONFIG --atleast-version=0.9.16 libotf; then :; else if ! $PKG_CONFIG --atleast-version=0.9.16 libotf; then
AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1], AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1],
[Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.]) [Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.])
fi fi
@ -3881,7 +3891,7 @@ if test "${HAVE_BE_APP}" = "yes"; then
AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1], AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1],
[Define to 1 if libotf has OTF_get_variation_glyphs.]) [Define to 1 if libotf has OTF_get_variation_glyphs.])
fi fi
if $PKG_CONFIG --atleast-version=0.9.16 libotf; then :; else if ! $PKG_CONFIG --atleast-version=0.9.16 libotf; then
AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1], AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1],
[Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.]) [Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.])
fi fi
@ -4199,7 +4209,7 @@ module_env_snippet_27="$srcdir/src/module-env-27.h"
module_env_snippet_28="$srcdir/src/module-env-28.h" module_env_snippet_28="$srcdir/src/module-env-28.h"
module_env_snippet_29="$srcdir/src/module-env-29.h" module_env_snippet_29="$srcdir/src/module-env-29.h"
module_env_snippet_30="$srcdir/src/module-env-30.h" module_env_snippet_30="$srcdir/src/module-env-30.h"
emacs_major_version=`AS_ECHO([$PACKAGE_VERSION]) | sed 's/[[.]].*//'` emacs_major_version="${PACKAGE_VERSION%%.*}"
AC_SUBST([emacs_major_version]) AC_SUBST([emacs_major_version])
### Emacs Lisp native compiler support ### Emacs Lisp native compiler support
@ -4309,16 +4319,14 @@ if test "${with_native_compilation}" != "no"; then
# available. (We filter out the gcc4 packages, because they # available. (We filter out the gcc4 packages, because they
# don't support jit, and they have names like "gcc49" that # don't support jit, and they have names like "gcc49" that
# sort later than "gcc11".) # sort later than "gcc11".)
PORT_PACKAGE=`port installed active | grep '^ *gcc@<:@0-9@:>@* ' | \ PORT_PACKAGE=$(port installed active | grep '^ *gcc@<:@0-9@:>@* ' | \
awk '{ print $1; }' | grep -v 'gcc4@<:@0-9@:>@' | \ awk '{ print $1; }' | grep -v 'gcc4@<:@0-9@:>@' | \
sort -V | tail -n 1` sort -V | tail -n 1)
if test -n "$PORT_PACKAGE"; then if test -n "$PORT_PACKAGE"; then
emacs_val=`port contents $PORT_PACKAGE | grep libgccjit.h` MAC_CFLAGS="-I$(dirname $(port contents $PORT_PACKAGE | \
emacs_val=`dirname $emacs_val` grep libgccjit.h))"
MAC_CFLAGS="-I$emacs_val" MAC_LIBS="-L$(dirname $(port contents $PORT_PACKAGE | \
emacs_val=`port contents $PORT_PACKAGE | grep libgccjit.dylib` grep libgccjit.dylib))"
emacs_val=`dirname $emacs_val`
MAC_LIBS="-L$emacs_val"
fi fi
fi fi
@ -4988,7 +4996,7 @@ gai_strerror sync \
getpwent endpwent getgrent endgrent \ getpwent endpwent getgrent endgrent \
renameat2 \ renameat2 \
cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np \ cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np \
pthread_set_name_np]) pthread_set_name_np sysconf])
LIBS=$OLD_LIBS LIBS=$OLD_LIBS
if test "$ac_cv_func_pthread_setname_np" = "yes"; then if test "$ac_cv_func_pthread_setname_np" = "yes"; then
@ -6530,6 +6538,174 @@ fi
AC_SUBST([WINDOW_SYSTEM_OBJ]) AC_SUBST([WINDOW_SYSTEM_OBJ])
AC_DEFUN([emacs_PAGE_SIZE],
[
AC_CACHE_CHECK([for the page size, in bytes],
[emacs_cv_page_size],
[AS_IF([test "x$ac_cv_func_sysconf" = "xyes"],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([
AC_INCLUDES_DEFAULT
[#include <stdio.h>
]],[[
FILE *file;
long pagesize;
file = fopen ("conftest.out", "w");
if (!file)
exit (1);
#ifdef _SC_PAGESIZE
pagesize = sysconf (_SC_PAGESIZE);
#else /* !_SC_PAGESIZE */
pagesize = sysconf (_SC_PAGE_SIZE);
#endif
if (pagesize < 0)
exit (1);
fprintf (file, "%ld\n", pagesize);
fflush (file);
fclose (file);
exit (0);
]])], [emacs_cv_page_size=`cat conftest.out`],
[AC_MSG_ERROR([Could not determine the page size])])],
[AS_IF([test "x$ac_cv_func_getpagesize" = "xyes"],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([
AC_INCLUDES_DEFAULT
[#include <stdio.h>
]],[[
FILE *file;
long pagesize;
file = fopen ("conftest.out", "w");
if (!file)
exit (1);
pagesize = getpagesize ();
if (pagesize < 0)
exit (1);
fprintf (file, "%ld\n", pagesize);
fflush (file);
fclose (file);
exit (0);
]])], [emacs_cv_page_size=`cat conftest.out`],
[AC_MSG_ERROR([Could not determine the page size])])])])])
AC_DEFINE_UNQUOTED([EMACS_PAGE_SIZE], [$emacs_cv_page_size],
[Define to the system page size, in bytes.])
])
AC_DEFUN([emacs_WRITE_FAULT_SIGNAL],
[
AC_CHECK_FUNCS([posix_memalign aligned_alloc valloc memalign])
AS_CASE(["$ac_cv_func_posix_memalign$ac_cv_func_aligned_alloc\
$ac_cv_func_valloc$ac_cv_func_memalign"], [*yes*], [],
[AC_MSG_ERROR([Cannot find a way to allocate page aligned memory])])
AC_CACHE_CHECK([for signal sent upon writing to protected memory],
[emacs_cv_protection_fault_signal],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([
AC_INCLUDES_DEFAULT
[
#include <sys/mman.h>
#if defined HAVE_VALLOC || defined HAVE_MEMALIGN
#include <malloc.h>
#endif /* HAVE_VALLOC || HAVE_MEMALIGN */
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
static volatile int sentsig;
static jmp_buf env;
static void
handlesigbus (signal)
int signal;
{
sentsig = SIGBUS;
longjmp (env, 1);
}
static void
handlesigsegv (signal)
int signal;
{
sentsig = SIGSEGV;
longjmp (env, 1);
}
]], [[
char *mem;
FILE *file;
signal (SIGBUS, handlesigbus);
signal (SIGSEGV, handlesigsegv);
#ifdef HAVE_ALIGNED_ALLOC
mem = aligned_alloc (EMACS_PAGE_SIZE, EMACS_PAGE_SIZE);
if (!mem)
exit (1);
#elif defined HAVE_POSIX_MEMALIGN
if (posix_memalign (&mem, EMACS_PAGE_SIZE,
EMACS_PAGE_SIZE))
exit (1);
#elif defined HAVE_MEMALIGN
mem = memalign (EMACS_PAGE_SIZE, EMACS_PAGE_SIZE);
if (!mem)
exit (1);
#elif defined HAVE_VALLOC
mem = valloc (EMACS_PAGE_SIZE);
if (!mem)
exit (1);
#endif
mprotect (mem, EMACS_PAGE_SIZE, PROT_READ);
if (!setjmp (env))
*mem = 1;
if (!sentsig)
exit (1);
file = fopen ("conftest.out", "w");
if (sentsig == SIGBUS)
{
fputs ("SIGBUS\n", file);
fflush (file);
fclose (file);
}
else
{
fputs ("SIGSEGV\n", file);
fflush (file);
fclose (file);
}
exit (0);
]])],
[emacs_cv_protection_fault_signal=`cat conftest.out`],
[AC_MSG_ERROR([Could not determine whether to use SIGBUS])])])
AC_DEFINE_UNQUOTED([WRITE_PROTECT_SIGNAL],
[$emacs_cv_protection_fault_signal],
[Signal sent upon a write protection fault.])
])
dnl Incremental GC setup.
dnl Determine the page size of the system.
dnl Then determine the signal raised during write
dnl protection faults.
AS_IF([test x"$with_incremental_gc" = x"yes"],
# Look for mprotect.
[AC_CHECK_FUNC([mprotect], [],
[AC_MSG_ERROR([mprotect not found.])])
# Determine the page size.
emacs_PAGE_SIZE
# Determine the signal raised due to a memory protection faults.
emacs_WRITE_FAULT_SIGNAL
# Finally, enable the incremental garbage collector.
AC_DEFINE([USE_INCREMENTAL_GC], [1],
[Define to 1 if garbage collection should run incrementally])])
AH_TOP([/* GNU Emacs site configuration template file. AH_TOP([/* GNU Emacs site configuration template file.
Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2021 Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2021

View file

@ -1245,7 +1245,6 @@ Manual}.
These four keywords are not really variables; setting them in any These four keywords are not really variables; setting them in any
other context has no special meaning. other context has no special meaning.
@cindex fallback modes
If you're editing a file across Emacs versions, and a new mode has If you're editing a file across Emacs versions, and a new mode has
been introduced to handle a file in a newer Emacs version, you can use been introduced to handle a file in a newer Emacs version, you can use
several @code{mode} entries to use the new mode (called several @code{mode} entries to use the new mode (called

View file

@ -2289,15 +2289,10 @@ behavior by using the options @code{image-auto-resize} and
@code{image-auto-resize-on-window-resize}. @code{image-auto-resize-on-window-resize}.
@findex image-transform-fit-to-window @findex image-transform-fit-to-window
@kindex s w (Image mode)
@findex image-transform-set-percent @findex image-transform-set-percent
@kindex s p (Image mode)
@findex image-transform-set-scale @findex image-transform-set-scale
@kindex s s (Image mode)
@findex image-transform-reset-to-initial @findex image-transform-reset-to-initial
@kindex s 0 (Image mode)
@findex image-transform-reset-to-original @findex image-transform-reset-to-original
@kindex s o (Image mode)
To resize the image manually you can use the command To resize the image manually you can use the command
@code{image-transform-fit-to-window} bound to @kbd{s w} that fits the @code{image-transform-fit-to-window} bound to @kbd{s w} that fits the
image to both the window height and width. To scale the image to a image to both the window height and width. To scale the image to a
@ -2358,94 +2353,6 @@ frames at once. You can go to a specific frame with @kbd{F}
(@code{image-reverse-speed}) reverses it. The command @kbd{a 0} (@code{image-reverse-speed}) reverses it. The command @kbd{a 0}
(@code{image-reset-speed}) resets the speed to the original value. (@code{image-reset-speed}) resets the speed to the original value.
In addition to the above key bindings, which are specific to Image
mode, images shown in any Emacs buffer have special key bindings when
point is at or inside the image:
@table @kbd
@cindex resize images
@cindex image resize
@findex image-increase-size
@kindex i + (Image mode)
@item i +
Increase the image size (@code{image-increase-size}) by 20%. Prefix
numeric argument controls the increment; the value of @var{n} means to
multiply the size by the factor of @w{@code{1 + @var{n} / 10}}, so
@w{@kbd{C-u 5 i +}} means to increase the size by 50%.
@findex image-decrease-size
@kindex i - (Image mode)
@item i -
Decrease the image size (@code{image-increase-size}) by 20%. Prefix
numeric argument controls the decrement; the value of @var{n} means to
multiply the size by the factor of @w{@code{1 - @var{n} / 10}}, so
@w{@kbd{C-u 3 i -}} means to decrease the size by 30%.
@cindex rotating images
@cindex image rotation
@findex image-rotate
@kindex i r (Image mode)
@item i r
Rotate the image by 90 degrees clockwise (@code{image-rotate}).
With the prefix argument, rotate by 90 degrees counter-clockwise instead.
Note that this command is not available for sliced images.
@findex image-flip-horizontally
@kindex i h (Image mode)
@item i h
Flip the image horizontally (@code{image-flip-horizontally}). This
presents the image as if reflected in a vertical mirror.
Note that this command is not available for sliced images.
@findex image-flip-vertically
@kindex i v (Image mode)
@item i v
Flip the image vertically (@code{image-flip-vertically}). This
presents the image as if reflected in a horizontal mirror.
Note that this command is not available for sliced images.
@findex image-save
@kindex i o (Image mode)
@item i o
Save the image to a file (@code{image-save}). This command prompts
you for the name of the file to save the image.
@cindex cropping images
@vindex image-crop-crop-command
@findex image-crop
@kindex i c (Image mode)
@item i c
Crop the image (@code{image-crop}). This command is available only if
your system has an external program installed that can be used for
cropping and cutting of images; the user option
@code{image-crop-crop-command} determines what program to use, and
defaults to the ImageMagick's @command{convert} program. The command
displays the image with a rectangular frame superimposed on it, and
lets you use the mouse to move and resize the frame. Type @kbd{m} to
cause mouse movements to move the frame instead of resizing it; type
@kbd{s} to move a square frame instead. When you are satisfied with
the position and size of the cropping frame, type @kbd{@key{RET}} to
actually crop the part under the frame; or type @kbd{q} to exit
without cropping. You can then save the cropped image using @w{@kbd{i
o}} or @w{@kbd{M-x image-save}}.
@findex image-cut
@kindex i x (Image mode)
@vindex image-cut-color
@vindex image-crop-cut-command
@item i x
Cut a rectangle from the image (@code{image-cut}). This works the
same as @code{image-crop} (and also requires an external program,
defined by the variable @code{image-crop-cut-command}, to perform the
image cut), but instead of cropping the image, it removes the part
inside the frame and fills that part with the color specified by
@code{image-cut-color}. With prefix argument, the command prompts for
the color to use.
@end table
The size and rotation commands are ``repeating'', which means that you
can continue adjusting the image without using the @kbd{i} prefix.
@cindex ImageMagick support @cindex ImageMagick support
@vindex imagemagick-enabled-types @vindex imagemagick-enabled-types
@vindex imagemagick-types-inhibit @vindex imagemagick-types-inhibit

View file

@ -313,27 +313,19 @@ may be defined in your Emacs session. For example, if a command
called @code{authorize-me} was defined, Emacs could only complete called @code{authorize-me} was defined, Emacs could only complete
as far as @samp{aut}.) as far as @samp{aut}.)
If you type @kbd{@key{TAB}} again immediately, it cannot determine If you type @key{TAB} again immediately, it cannot determine the
the next character; it could be @samp{-}, @samp{a}, or @samp{c}. So next character; it could be @samp{-}, @samp{a}, or @samp{c}. So it
it does not add any characters; instead, @key{TAB} displays a list of does not add any characters; instead, @key{TAB} displays a list of all
all possible completions in another window. possible completions in another window.
Next, type @kbd{-f}. The minibuffer now contains @samp{auto-f}, and Next, type @kbd{-f}. The minibuffer now contains @samp{auto-f}, and
the only command name that starts with this is @code{auto-fill-mode}. the only command name that starts with this is @code{auto-fill-mode}.
If you now type @kbd{@key{TAB}}, completion fills in the rest of the If you now type @key{TAB}, completion fills in the rest of the
argument @samp{auto-fill-mode} into the minibuffer. argument @samp{auto-fill-mode} into the minibuffer.
Hence, typing just @kbd{a u @key{TAB} - f @key{TAB}} allows you to Hence, typing just @kbd{a u @key{TAB} - f @key{TAB}} allows you to
enter @samp{auto-fill-mode}. enter @samp{auto-fill-mode}.
@key{TAB} also works while point is not at the end of the
minibuffer. In that case, it will fill in text both at point and at
the end of the minibuffer. If you type @kbd{M-x autocm}, then press
@kbd{C-b} to move point before the @samp{m}, you can type
@kbd{@key{TAB}} to insert the text @samp{onf-} at point and @samp{ode}
at the end of the minibuffer, so that the minibuffer contains
@samp{autoconf-mode}.
@node Completion Commands @node Completion Commands
@subsection Completion Commands @subsection Completion Commands

View file

@ -329,15 +329,15 @@ version of the package, a newer version is also installed.
@section Package Installation @section Package Installation
@findex package-install @findex package-install
@findex package-upgrade @findex package-update
@findex package-upgrade-all @findex package-update-all
Packages are most conveniently installed using the package menu Packages are most conveniently installed using the package menu
(@pxref{Package Menu}), but you can also use the command @kbd{M-x (@pxref{Package Menu}), but you can also use the command @kbd{M-x
package-install}. This prompts for the name of a package with the package-install}. This prompts for the name of a package with the
@samp{available} status, then downloads and installs it. Similarly, @samp{available} status, then downloads and installs it. Similarly,
if you want to upgrade a package, you can use the @kbd{M-x if you want to update a package, you can use the @kbd{M-x
package-upgrade} command, and if you want to upgrade all the packages, package-update} command, and if you just want to update all the
you can use the @kbd{M-x package-upgrade-all} command. packages, you can use the @kbd{M-x package-update-all} command.
@cindex package requirements @cindex package requirements
A package may @dfn{require} certain other packages to be installed, A package may @dfn{require} certain other packages to be installed,
@ -551,8 +551,8 @@ bugs.
source code for a package directly from source. The command will also source code for a package directly from source. The command will also
automatically ensure that all files are byte-compiled and auto-loaded, automatically ensure that all files are byte-compiled and auto-loaded,
just like with a regular package. Packages installed this way behave just like with a regular package. Packages installed this way behave
just like any other package. You can upgrade them using just like any other package. You can update them using
@code{package-upgrade} or @code{package-upgrade-all} and delete them @code{package-update} or @code{package-update-all} and delete them
again using @code{package-delete}. They are even displayed in the again using @code{package-delete}. They are even displayed in the
regular package listing. If you just wish to clone the source of a regular package listing. If you just wish to clone the source of a
package, without adding it to the package list, use package, without adding it to the package list, use
@ -578,80 +578,3 @@ from the package directory (@pxref{Package Files}) to your checkout
and initializes the code. Note that you might have to use and initializes the code. Note that you might have to use
@code{package-vc-refresh} to repeat the initialization and update the @code{package-vc-refresh} to repeat the initialization and update the
autoloads. autoloads.
@subsection Specifying Package Sources
@cindex package specification
@cindex specification, for source packages
To install a package from source, Emacs must know where to get the
package's source code (such as a code repository) and basic
information about the structure of the code (such as the main file in
a multi-file package). A @dfn{package specification} describes these
properties.
When supported by a package archive (@pxref{Package
Archives,,,elisp, The Emacs Lisp Reference Manual}), Emacs can
automatically download a package's specification from said archive.
If the first argument passed to @code{package-vc-install} is a symbol
naming a package, then Emacs will use the specification provided by
the archive for that package.
@example
@group
;; Emacs will download BBDB's specification from GNU ELPA:
(package-vc-install 'bbdb)
@end group
@end example
The first argument to @code{package-vc-install} may also be a
package specification. This allows you to install source packages
from locations other than the known archives listed in the user option
@code{package-archives}. A package specification is a list of the
form @code{(@var{name} . @var{spec})}, in which @var{spec} should be a
property list using any of the keys in the table below.
For definitions of basic terms for working with code repositories and
version control systems, see @ref{VCS Concepts,,,emacs, The GNU Emacs
Manual}.
@table @code
@item :url
A string providing the URL that specifies the repository from which to
fetch the package's source code.
@item :branch
A string providing the revision of the code to install. Do not
confuse this with a package's version number.
@item :lisp-dir
A string providing the repository-relative name of the directory to
use for loading the Lisp sources, which defaults to the root directory
of the repository.
@item :main-file
A string providing the main file of the project, from which to gather
package metadata. If not given, the default is the package name with
".el" appended to it.
@item :doc
A string providing the repository-relative name of the documentation
file from which to build an Info file. This can be a Texinfo file or
an Org file.
@item :vc-backend
A symbol naming the VC backend to use for downloading a copy of the
package's repository (@pxref{Version Control Systems,,,emacs, The GNU
Emacs Manual}). If omitted, Emacs will attempt to make a guess based
on the provided URL, or, failing that, the process will fall back onto
the value of @code{package-vc-default-backend}.
@end table
@example
@group
;; Specifying information manually:
(package-vc-install
'(bbdb :url "https://git.savannah.nongnu.org/git/bbdb.git"
:lisp-dir "lisp"
:doc "doc/bbdb.texi"))
@end group
@end example

View file

@ -856,7 +856,7 @@ customizations.
@cindex dribble file @cindex dribble file
@cindex logging keystrokes @cindex logging keystrokes
One way to record the input to Emacs precisely is to write a dribble One way to record the input to Emacs precisely is to write a dribble
file. To start the file, use the command @w{@kbd{M-x open-dribble-file}}. file. To start the file, use the @kbd{M-x open-dribble-file} command.
From then on, Emacs copies all your input to the specified dribble From then on, Emacs copies all your input to the specified dribble
file until the Emacs process is killed. Be aware that sensitive file until the Emacs process is killed. Be aware that sensitive
information (such as passwords) may end up recorded in the dribble information (such as passwords) may end up recorded in the dribble
@ -1071,13 +1071,9 @@ backtrace for the error. To make a backtrace for the error, use
say, you must give that command and then make the bug happen). This say, you must give that command and then make the bug happen). This
causes the error to start the Lisp debugger, which shows you a causes the error to start the Lisp debugger, which shows you a
backtrace. Copy the text of the debugger's backtrace into the bug backtrace. Copy the text of the debugger's backtrace into the bug
report. (The backtrace is more detailed if you load the relevant Lisp report. @xref{Edebug,, Edebug, elisp, the Emacs Lisp Reference
@file{*.el} source files before triggering the error, so do that if Manual}, for information on debugging Emacs Lisp programs with the
you know how to find and load those files.) Edebug package.
To debug the error, we suggest using Edebug. @xref{Edebug,, Edebug,
elisp, the Emacs Lisp Reference Manual}, for information on debugging
Emacs Lisp programs with the Edebug package.
This use of the debugger is possible only if you know how to make the This use of the debugger is possible only if you know how to make the
bug happen again. If you can't make it happen again, at least copy bug happen again. If you can't make it happen again, at least copy

View file

@ -6604,11 +6604,10 @@ works. You will probably need to use @kbd{C-h f}
(@code{describe-function}). The newer version uses a conditional to (@code{describe-function}). The newer version uses a conditional to
determine whether the buffer has been narrowed. determine whether the buffer has been narrowed.
Also, the modern version of @code{what-line} uses (Also, it uses @code{line-number-at-pos}, which among other simple
@code{line-number-at-pos}, which among other simple expressions, such expressions, such as @code{(goto-char (point-min))}, moves point to
as @code{(goto-char (point-min))}, moves point to the beginning of the the beginning of the current line with @code{(forward-line 0)} rather
current line with @code{(forward-line 0)} rather than than @code{beginning-of-line}.)
@code{beginning-of-line}.)
The @code{what-line} function as shown here has a documentation line The @code{what-line} function as shown here has a documentation line
and is interactive, as you would expect. The next two lines use the and is interactive, as you would expect. The next two lines use the

View file

@ -959,9 +959,9 @@ infinite recursion.
@defun buffer-match-p condition buffer-or-name &optional arg @defun buffer-match-p condition buffer-or-name &optional arg
This function checks if a buffer designated by @code{buffer-or-name} This function checks if a buffer designated by @code{buffer-or-name}
satisfies the specified @code{condition}. Optional third argument satisfies a @code{condition}. Optional third argument @var{arg} is
@var{arg} is passed to the predicate function in @var{condition}. A passed to the predicate function in @var{condition}. A condition can
valid @var{condition} can be one of the following: be one of the following:
@itemize @bullet{} @itemize @bullet{}
@item @item
A string, interpreted as a regular expression. The buffer A string, interpreted as a regular expression. The buffer
@ -990,23 +990,21 @@ Satisfied if @emph{all} the conditions in @var{conds} satisfy
Satisfied if the buffer's major mode derives from @var{expr}. Satisfied if the buffer's major mode derives from @var{expr}.
@item major-mode @item major-mode
Satisfied if the buffer's major mode is equal to @var{expr}. Prefer Satisfied if the buffer's major mode is equal to @var{expr}. Prefer
using @code{derived-mode} instead, when both can work. using @code{derived-mode} instead when both can work.
@end table @end table
@item t @item t
Satisfied by any buffer. A convenient alternative to @code{""} (empty Satisfied by any buffer. A convenient alternative to @code{""} (empty
string) or @code{(and)} (empty conjunction). string), @code{(and)} (empty conjunction) or @code{always}.
@end itemize @end itemize
@end defun @end defun
@defun match-buffers condition &optional buffer-list arg @defun match-buffers condition &optional buffer-list arg
This function returns a list of all buffers that satisfy the This function returns a list of all buffers that satisfy a
@code{condition}. If no buffers match, the function returns @code{condition}, as defined for @code{buffer-match-p}. By default
@code{nil}. The argument @var{condition} is as defined in all buffers are considered, but this can be restricted via the second
@code{buffer-match-p} above. By default, all the buffers are optional @code{buffer-list} argument. Optional third argument
considered, but this can be restricted via the optional argument @var{arg} will be used by @var{condition} in the same way as
@code{buffer-list}, which should be a list of buffers to consider. @code{buffer-match-p} does.
Optional third argument @var{arg} will be passed to @var{condition} in
the same way as @code{buffer-match-p} does.
@end defun @end defun
@node Creating Buffers @node Creating Buffers

View file

@ -1960,8 +1960,8 @@ end-position of a drag event, this position list may represent a
location outside the boundaries of the initially selected frame, in location outside the boundaries of the initially selected frame, in
which case the list contains that frame in place of a window. which case the list contains that frame in place of a window.
The @code{track-mouse} macro enables generation of motion The special form @code{track-mouse} enables generation of motion
events within its body. Outside of @code{track-mouse} body, Emacs events within its body. Outside of @code{track-mouse} forms, Emacs
does not generate events for mere motion of the mouse, and these does not generate events for mere motion of the mouse, and these
events do not appear. @xref{Mouse Tracking}. events do not appear. @xref{Mouse Tracking}.
@ -2395,17 +2395,6 @@ as @code{set-language-environment}), use the
;; Get the full localized name of the language ;; Get the full localized name of the language
(w32-get-locale-info language-id t) (w32-get-locale-info language-id t)
@end smallexample @end smallexample
@cindex @code{end-session} event
@item end-session
This event is generated on MS-Windows when the operating system
informs Emacs that the user terminated the interactive session, or
that the system is shutting down. The standard definition of this
event is to invoke the @code{kill-emacs} command (@pxref{Killing
Emacs}) so as to shut down Emacs in an orderly fashion; if there are
unsaved changes, this will produce auto-save files
(@pxref{Auto-Saving}) that the user can use after restarting the
session to restore the unsaved edits.
@end table @end table
If one of these events arrives in the middle of a key sequence---that If one of these events arrives in the middle of a key sequence---that
@ -2454,7 +2443,7 @@ into another window. That produces a pair of events like these:
The frame with input focus might not take up the entire screen, and The frame with input focus might not take up the entire screen, and
the user might move the mouse outside the scope of the frame. Inside the user might move the mouse outside the scope of the frame. Inside
the @code{track-mouse} macro, that produces an event like this: the @code{track-mouse} special form, that produces an event like this:
@smallexample @smallexample
(mouse-movement (#<frame *ielm* 0x102849a30> nil (563 . 205) 532301936)) (mouse-movement (#<frame *ielm* 0x102849a30> nil (563 . 205) 532301936))

View file

@ -1809,9 +1809,6 @@ wish the program to continue execution despite an error in a subroutine.
In these cases, you would use @code{condition-case} to establish In these cases, you would use @code{condition-case} to establish
@dfn{error handlers} to recover control in case of error. @dfn{error handlers} to recover control in case of error.
For reporting problems without terminating the execution of the
current command, consider issuing a warning instead. @xref{Warnings}.
Resist the temptation to use error handling to transfer control from Resist the temptation to use error handling to transfer control from
one part of the program to another; use @code{catch} and @code{throw} one part of the program to another; use @code{catch} and @code{throw}
instead. @xref{Catch and Throw}. instead. @xref{Catch and Throw}.

View file

@ -264,12 +264,11 @@ have any number of prefixes.
@end table @end table
@cindex @code{custom-group} property @cindex @code{custom-group} property
The variables, faces, and subgroups of a group are stored in the The variables and subgroups of a group are stored in the
@code{custom-group} property of the group's symbol. @xref{Symbol @code{custom-group} property of the group's symbol. @xref{Symbol
Plists}. The value of that property is a list of pairs whose Plists}. The value of that property is a list of pairs whose
@code{car} is the symbol of the variable or the face or the subgroup, @code{car} is the variable or subgroup symbol and the @code{cdr} is
and the @code{cdr} is one of the corresponding symbols either @code{custom-variable} or @code{custom-group}.
@code{custom-variable}, @code{custom-face}, or @code{custom-group}.
@end defmac @end defmac
@defopt custom-unlispify-remove-prefixes @defopt custom-unlispify-remove-prefixes

View file

@ -310,29 +310,29 @@ reformatted, with undesirable results. Instead, use @code{(message
"%s" @var{string})}. "%s" @var{string})}.
@end defun @end defun
The following facilities allow users and Lisp programs to control how
echo-area messages are displayed.
@defvar set-message-function @defvar set-message-function
If this variable is non-@code{nil}, it should be a function of one If this variable is non-@code{nil}, it should be a function of one
argument, the text of a message to display in the echo area. That argument, the text of a message to display in the echo area. This
function will be called by @code{message} and related functions. If function will be called by @code{message} and related functions. If
the function returns @code{nil}, the message is displayed in the echo the function returns @code{nil}, the message is displayed in the echo
area as usual. If the function returns a string, that string is area as usual. If this function returns a string, that string is
displayed in the echo area @emph{instead} of the original message. If displayed in the echo area instead of the original one. If this
the function returns any other non-@code{nil} value, that means the function returns other non-@code{nil} values, that means the message
message was already handled, so @code{message} will not display was already handled, so @code{message} will not display anything in
anything in the echo area. the echo area. See also @code{clear-message-function} that can be
used to clear the message displayed by this function.
The default value calls @code{set-minibuffer-message}, described The default value is the function that displays the message at the end
below. of the minibuffer when the minibuffer is active. However, if the text
shown in the active minibuffer has the @code{minibuffer-message} text
property (@pxref{Special Properties}) on some character, the message
will be displayed before the first character having that property.
@end defvar @end defvar
@defvar clear-message-function @defvar clear-message-function
If this variable is non-@code{nil}, it should be a function of no If this variable is non-@code{nil}, @code{message} and related
arguments; @code{message} and related functions call it when their functions call it with no arguments when their argument message is
argument message is @code{nil} or the empty string, to clear the echo @code{nil} or the empty string.
area.
Usually this function is called when the next input event arrives Usually this function is called when the next input event arrives
after displaying an echo-area message. The function is expected to after displaying an echo-area message. The function is expected to
@ -358,51 +358,11 @@ with the same text; if the last function in the list returns
function returns a non-@code{nil} value that is not a string, the function returns a non-@code{nil} value that is not a string, the
message is considered to be handled, and no further functions in the message is considered to be handled, and no further functions in the
list are called. list are called.
The three useful functions to be put in the list that is the value of
this option are described below.
@end defopt @end defopt
@defun set-minibuffer-message message
This function displays @var{message} in the echo-area when the
minibuffer is not active, and at the end of the minibuffer when the
minibuffer is active. However, if the text shown in the active
minibuffer has the @code{minibuffer-message} text property
(@pxref{Special Properties}) on some character, the message will be
displayed before the first character having that property.
This function is by default the only member of the list in
@code{set-message-functions}.
@end defun
@vindex inhibit-message-regexps
@defun inhibit-message message
If an echo-area @var{message} matches any regexp in the list that is
the value of the user option @code{inhibit-message-regexps}, this
function suppresses the display of that message and returns a
non-@code{nil} value that is not a string. Thus, if this function is
in the list @code{set-message-functions}, the rest of the functions in
the list will not be called when @var{message} matches the regexps in
@code{inhibit-message-regexps}. To ensure a matching @var{message}
will never be displayed, make this function be the first element of
the list in @code{set-message-functions}.
@end defun
@vindex multi-message-max
@vindex multi-message-timeout
@defun set-multi-message message
This function accumulates several echo-area messages emitted one after
another, and returns them as a single string in which individual
messages are separated by newlines. Up to @code{multi-message-max}
recent messages can be accumulated. The accumulated messages are
discarded when more than @code{multi-message-timeout} seconds have
elapsed since the time the first message was emitted.
@end defun
@defvar inhibit-message @defvar inhibit-message
When this variable is non-@code{nil}, @code{message} and related functions When this variable is non-@code{nil}, @code{message} and related functions
will not display any messages in the Echo Area. Echo-area messages will not use the Echo Area to display messages.
are still logged in the @file{*Messages*} buffer, though.
@end defvar @end defvar
@defmac with-temp-message message &rest body @defmac with-temp-message message &rest body
@ -752,8 +712,7 @@ echo area (which is really a special use of the minibuffer window;
@cindex warnings @cindex warnings
@dfn{Warnings} are a facility for a program to inform the user of a @dfn{Warnings} are a facility for a program to inform the user of a
possible problem, but continue running (as opposed to signaling an possible problem, but continue running.
error, @pxref{Errors}).
@menu @menu
* Warning Basics:: Warnings concepts and functions to report them. * Warning Basics:: Warnings concepts and functions to report them.
@ -766,74 +725,69 @@ error, @pxref{Errors}).
@subsection Warning Basics @subsection Warning Basics
@cindex severity level @cindex severity level
Every warning is a textual message, which explains the problem for Every warning has a textual message, which explains the problem for
the user, with the associated @dfn{severity level} which is a symbol. the user, and a @dfn{severity level} which is a symbol. Here are the
Here are the supported severity levels, in order of decreasing possible severity levels, in order of decreasing severity, and their
severity, and their meanings: meanings:
@table @code @table @code
@item :emergency @item :emergency
A problem that will seriously impair Emacs operation soon A problem that will seriously impair Emacs operation soon
if the user does not attend to it promptly. if you do not attend to it promptly.
@item :error @item :error
A report about data or circumstances that are inherently wrong. A report of data or circumstances that are inherently wrong.
@item :warning @item :warning
A report about data or circumstances that are not inherently wrong, A report of data or circumstances that are not inherently wrong, but
but raise suspicion of a possible problem. raise suspicion of a possible problem.
@item :debug @item :debug
A report of information that may be useful if the user is currently A report of information that may be useful if you are debugging.
debugging the Lisp program which issues the warning.
@end table @end table
When your program encounters invalid input data, it can either When your program encounters invalid input data, it can either
signal a Lisp error by calling @code{error} or @code{signal} signal a Lisp error by calling @code{error} or @code{signal} or report
(@pxref{Signaling Errors}) or report a warning with severity a warning with severity @code{:error}. Signaling a Lisp error is the
@code{:error}. Signaling a Lisp error is the easiest thing to do, but easiest thing to do, but it means the program cannot continue
it means the signaling program cannot continue execution. If you want processing. If you want to take the trouble to implement a way to
to take the trouble of implementing a way to continue processing continue processing despite the bad data, then reporting a warning of
despite the invalid data, then reporting a warning of severity severity @code{:error} is the right way to inform the user of the
@code{:error} is the right way of informing the user of the problem. problem. For instance, the Emacs Lisp byte compiler can report an
For instance, the Emacs Lisp byte compiler can report an error that error that way and continue compiling other functions. (If the
way and continue compiling other functions. (If the program signals a program signals a Lisp error and then handles it with
Lisp error and then handles it with @code{condition-case}, the user @code{condition-case}, the user won't see the error message; it could
won't see the error message; reporting that as a warning instead show the message to the user by reporting it as a warning.)
avoids that problem.)
@c FIXME: Why use "(bytecomp)" instead of "'bytecomp" or simply
@c "bytecomp" here? The parens are part of warning-type-format but
@c not part of the warning type. --xfq
@cindex warning type @cindex warning type
In addition to severity level, each warning has a @dfn{warning type} Each warning has a @dfn{warning type} to classify it. The type is a
to classify it. The warning type is either a symbol or a list of list of symbols. The first symbol should be the custom group that you
symbols. If it is a symbol, it should be the custom group that you use for the program's user options. For example, byte compiler
use for the program's user options; if it is a list, the first element warnings use the warning type @code{(bytecomp)}. You can also
of the list should be that custom group. For example, byte compiler subcategorize the warnings, if you wish, by using more symbols in the
warnings use the warning type @code{(bytecomp)}. If the warning type list.
is a list, the elements of the list after the first one, which should
be arbitrary symbols, represent subcategories of the warning: they
will be displayed to the user to better explain the nature of the
warning.
@defun display-warning type message &optional level buffer-name @defun display-warning type message &optional level buffer-name
This function reports a warning, using the string @var{message} as the This function reports a warning, using @var{message} as the message
warning text and @var{type} as the warning type. @var{level} should and @var{type} as the warning type. @var{level} should be the
be the severity level, and defaults to @code{:warning} if omitted or severity level, with @code{:warning} being the default.
@code{nil}.
@var{buffer-name}, if non-@code{nil}, specifies the name of the buffer @var{buffer-name}, if non-@code{nil}, specifies the name of the buffer
for logging the warning message. By default, it is @file{*Warnings*}. for logging the warning. By default, it is @file{*Warnings*}.
@end defun @end defun
@defun lwarn type level message &rest args @defun lwarn type level message &rest args
This function reports a warning using the value returned by This function reports a warning using the value of @code{(format-message
@w{@code{(format-message @var{message} @var{args}@dots{})}} as the @var{message} @var{args}...)} as the message in the @file{*Warnings*}
message text in the @file{*Warnings*} buffer. In other respects it is buffer. In other respects it is equivalent to @code{display-warning}.
equivalent to @code{display-warning}.
@end defun @end defun
@defun warn message &rest args @defun warn message &rest args
This function reports a warning using the value returned by This function reports a warning using the value of @code{(format-message
@w{@code{(format-message @var{message} @var{args}@dots{})}} as the @var{message} @var{args}...)} as the message, @code{(emacs)} as the
message text, @code{emacs} as the warning type, and @code{:warning} as type, and @code{:warning} as the severity level. It exists for
the severity level. It exists for compatibility only; we recommend compatibility only; we recommend not using it, because you should
not using it, because you should specify a specific warning type. specify a specific warning type.
@end defun @end defun
@node Warning Variables @node Warning Variables
@ -848,16 +802,15 @@ This list defines the meaning and severity order of the warning
severity levels. Each element defines one severity level, severity levels. Each element defines one severity level,
and they are arranged in order of decreasing severity. and they are arranged in order of decreasing severity.
Each element has the form @w{@code{(@var{level} @var{string} Each element has the form @code{(@var{level} @var{string}
[@var{function}])}}, where @var{level} is the severity level it @var{function})}, where @var{level} is the severity level it defines.
defines. @var{string} specifies the textual description of this @var{string} specifies the textual description of this level.
level. @var{string} should use @samp{%s} to specify where to put the @var{string} should use @samp{%s} to specify where to put the warning
warning type information, or it can omit the @samp{%s} so as not to type information, or it can omit the @samp{%s} so as not to include
include that information. that information.
The optional @var{function}, if non-@code{nil}, is a function to call The optional @var{function}, if non-@code{nil}, is a function to call
with no arguments, to get the user's attention. A notable example is with no arguments, to get the user's attention.
@code{ding} (@pxref{Beeping}).
Normally you should not change the value of this variable. Normally you should not change the value of this variable.
@end defvar @end defvar
@ -866,19 +819,18 @@ Normally you should not change the value of this variable.
If non-@code{nil}, the value is a function to generate prefix text for If non-@code{nil}, the value is a function to generate prefix text for
warnings. Programs can bind the variable to a suitable function. warnings. Programs can bind the variable to a suitable function.
@code{display-warning} calls this function with the warnings buffer @code{display-warning} calls this function with the warnings buffer
the current buffer, and the function can insert text into it. That current, and the function can insert text in it. That text becomes
text becomes the beginning of the warning message. the beginning of the warning message.
The function is called with two arguments, the severity level and its The function is called with two arguments, the severity level and its
entry in @code{warning-levels}. It should return a list to use entry in @code{warning-levels}. It should return a list to use as the
@emph{instead} of that entry (the value need not be an actual member entry (this value need not be an actual member of
of @code{warning-levels}, but it must have the same structure). By @code{warning-levels}). By constructing this value, the function can
constructing this value, the function can change the severity of the change the severity of the warning, or specify different handling for
warning, or specify different handling for a given severity level. a given severity level.
If the variable's value is @code{nil}, there's no prefix text, before If the variable's value is @code{nil} then there is no function
the warning is displayed, starting with the @var{string} part of the to call.
entry in @code{warning-levels} corresponding to the warning's level.
@end defvar @end defvar
@defvar warning-series @defvar warning-series
@ -886,18 +838,17 @@ Programs can bind this variable to @code{t} to say that the next
warning should begin a series. When several warnings form a series, warning should begin a series. When several warnings form a series,
that means to leave point on the first warning of the series, rather that means to leave point on the first warning of the series, rather
than keep moving it for each warning so that it appears on the last one. than keep moving it for each warning so that it appears on the last one.
The series ends when the local binding of this variable is unbound and The series ends when the local binding is unbound and
@code{warning-series} becomes @code{nil} again. @code{warning-series} becomes @code{nil} again.
The value can also be a symbol with a function definition. That is The value can also be a symbol with a function definition. That is
equivalent to @code{t}, except that the next warning will also call equivalent to @code{t}, except that the next warning will also call
the function with no arguments with the warnings buffer the current the function with no arguments with the warnings buffer current. The
buffer. The function can, for example, insert text which will serve function can insert text which will serve as a header for the series
as a header for the series of warnings. of warnings.
Once a series has begun, the value of this variable is a marker which Once a series has begun, the value is a marker which points to the
points to the buffer position in the warnings buffer of the start of buffer position in the warnings buffer of the start of the series.
the series.
The variable's normal value is @code{nil}, which means to handle The variable's normal value is @code{nil}, which means to handle
each warning separately. each warning separately.
@ -905,7 +856,7 @@ each warning separately.
@defvar warning-fill-prefix @defvar warning-fill-prefix
When this variable is non-@code{nil}, it specifies a fill prefix to When this variable is non-@code{nil}, it specifies a fill prefix to
use for filling the text of each warning. use for filling each warning's text.
@end defvar @end defvar
@defvar warning-fill-column @defvar warning-fill-column
@ -914,11 +865,11 @@ The column at which to fill warnings.
@defvar warning-type-format @defvar warning-type-format
This variable specifies the format for displaying the warning type This variable specifies the format for displaying the warning type
in the warning text. The result of formatting the type this way in the warning message. The result of formatting the type this way
gets included in the message under the control of the string in the gets included in the message under the control of the string in the
entry in @code{warning-levels}. The default value is @code{" (%s)"}. entry in @code{warning-levels}. The default value is @code{" (%s)"}.
If you bind it to the empty string @code{""} then the warning type If you bind it to @code{""} then the warning type won't appear at
won't appear at all. all.
@end defvar @end defvar
@node Warning Options @node Warning Options
@ -930,71 +881,38 @@ when a Lisp program reports a warning.
@defopt warning-minimum-level @defopt warning-minimum-level
This user option specifies the minimum severity level that should be This user option specifies the minimum severity level that should be
shown immediately to the user, by popping the warnings buffer in some shown immediately to the user. The default is @code{:warning}, which
window. The default is @code{:warning}, which means to show the means to immediately display all warnings except @code{:debug}
warning buffer for any warning severity except @code{:debug}. The warnings.
warnings of lower severity levels will still be written into the
warnings buffer, but the buffer will not be forced onto display.
@end defopt @end defopt
@defopt warning-minimum-log-level @defopt warning-minimum-log-level
This user option specifies the minimum severity level that should be This user option specifies the minimum severity level that should be
logged in the warnings buffer. Warnings of lower severity will be logged in the warnings buffer. The default is @code{:warning}, which
completely ignored: not written to the warnings buffer and not means to log all warnings except @code{:debug} warnings.
displayed. The default is @code{:warning}, which means to log
warnings of any severity except @code{:debug}.
@end defopt @end defopt
@defopt warning-suppress-types @defopt warning-suppress-types
This list specifies which warning types should not be displayed This list specifies which warning types should not be displayed
immediately when they occur. Each element of the list should be a immediately for the user. Each element of the list should be a list
list of symbols. If an element of this list has the same elements as of symbols. If its elements match the first elements in a warning
the first elements in a warning type, then the warning of that type type, then that warning is not displayed immediately.
will not be shown on display by popping the warnings buffer in some
window (the warning will still be logged in the warnings buffer).
For example, if the value of this variable is a list like this:
@lisp
((foo) (bar subtype))
@end lisp
@noindent
then warnings whose types are @code{foo} or @code{(foo)} or
@w{@code{(foo something)}} or @w{@code{(bar subtype other)}} will not
be shown to the user.
@end defopt @end defopt
@defopt warning-suppress-log-types @defopt warning-suppress-log-types
This list specifies which warning types should be ignored: not logged This list specifies which warning types should not be logged in the
in the warnings buffer and not shown to the user. The structure and warnings buffer. Each element of the list should be a list of
the matching of warning types are the same as for symbols. If it matches the first few elements in a warning type, then
@code{warning-suppress-types} above. that warning is not logged.
@end defopt @end defopt
@cindex warnings, suppressing during startup
@cindex prevent warnings in init files
During startup, Emacs delays showing any warnings until after it
loads and processes the site-wide and user's init files
(@pxref{Startup Summary}). Let-binding (@pxref{Local Variables}) the
values of these options around some code in your init files which
might emit a warning will therefore not work, because it will not be
in effect by the time the warning is actually processed. Thus, if you
want to suppress some warnings during startup, change the values of
the above options in your init file early enough, or put those
let-binding forms in your @code{after-init-hook} or
@code{emacs-startup-hook} functions. @xref{Init File}.
@node Delayed Warnings @node Delayed Warnings
@subsection Delayed Warnings @subsection Delayed Warnings
@cindex delayed warnings @cindex delayed warnings
@cindex warnings, delayed
Sometimes, you may wish to avoid showing a warning while a command is Sometimes, you may wish to avoid showing a warning while a command is
running, and only show it only after the end of the command. You can running, and only show it only after the end of the command. You can
use the function @code{delay-warning} for this. Emacs automatically use the function @code{delay-warning} for this.
delays any warnings emitted during the early stages of startup, and
shows them only after the init files are processed.
@defun delay-warning type message &optional level buffer-name @defun delay-warning type message &optional level buffer-name
This function is the delayed counterpart to @code{display-warning} This function is the delayed counterpart to @code{display-warning}
@ -1015,7 +933,7 @@ with the same form, and the same meanings, as the argument list of
@code{display-warning}. Immediately after running @code{display-warning}. Immediately after running
@code{post-command-hook} (@pxref{Command Overview}), the Emacs @code{post-command-hook} (@pxref{Command Overview}), the Emacs
command loop displays all the warnings specified by this variable, command loop displays all the warnings specified by this variable,
then resets the variable to @code{nil}. then resets it to @code{nil}.
@end defvar @end defvar
Programs which need to further customize the delayed warnings Programs which need to further customize the delayed warnings
@ -1024,9 +942,7 @@ mechanism can change the variable @code{delayed-warnings-hook}:
@defvar delayed-warnings-hook @defvar delayed-warnings-hook
This is a normal hook which is run by the Emacs command loop, after This is a normal hook which is run by the Emacs command loop, after
@code{post-command-hook}, in order to process and display delayed @code{post-command-hook}, in order to process and display delayed
warnings. Emacs also runs this hook during startup, after loading the warnings.
site-start and user init files (@pxref{Startup Summary}), because
warnings emitted before that are automatically delayed.
Its default value is a list of two functions: Its default value is a list of two functions:
@ -6920,7 +6836,7 @@ This function puts image @var{image} in front of @var{pos} in the
current buffer. The argument @var{pos} should be an integer or a current buffer. The argument @var{pos} should be an integer or a
marker. It specifies the buffer position where the image should appear. marker. It specifies the buffer position where the image should appear.
The argument @var{string} specifies the text that should hold the image The argument @var{string} specifies the text that should hold the image
as an alternative to the default @samp{x}. as an alternative to the default.
The argument @var{image} must be an image descriptor, perhaps returned The argument @var{image} must be an image descriptor, perhaps returned
by @code{create-image} or stored by @code{defimage}. by @code{create-image} or stored by @code{defimage}.
@ -6933,7 +6849,7 @@ buffer's text.
Internally, this function creates an overlay, and gives it a Internally, this function creates an overlay, and gives it a
@code{before-string} property containing text that has a @code{display} @code{before-string} property containing text that has a @code{display}
property whose value is the image. (Whew! that was a mouthful@dots{}) property whose value is the image. (Whew!)
@end defun @end defun
@defun remove-images start end &optional buffer @defun remove-images start end &optional buffer
@ -6980,47 +6896,41 @@ This function returns @code{t} if point is on an image, and @code{nil}
otherwise. otherwise.
@end defun @end defun
@cindex operations on images
Images inserted with the insertion functions above also get a local Images inserted with the insertion functions above also get a local
keymap installed in the text properties (or overlays) that span the keymap installed in the text properties (or overlays) that span the
displayed image. This keymap defines the following commands: displayed image. This keymap defines the following commands:
@table @kbd @table @kbd
@findex image-increase-size
@item i + @item i +
Increase the image size (@code{image-increase-size}) Increase the image size (@code{image-increase-size}). A prefix value
of @samp{4} means to increase the size by 40%. The default is 20%.
@findex image-decrease-size
@item i - @item i -
Decrease the image size (@code{image-decrease-size}). Decrease the image size (@code{image-increase-size}). A prefix value
of @samp{4} means to decrease the size by 40%. The default is 20%.
@findex image-rotate
@item i r @item i r
Rotate the image (@code{image-rotate}). Rotate the image by 90 degrees clockwise (@code{image-rotate}).
A prefix means to rotate by 90 degrees counter-clockwise instead.
@findex image-flip-horizontally
@item i h @item i h
Flip the image horizontally (@code{image-flip-horizontally}). Flip the image horizontally (@code{image-flip-horizontally}).
@findex image-flip-vertically
@item i v @item i v
Flip the image vertically (@code{image-flip-vertically}). Flip the image vertically (@code{image-flip-vertically}).
@findex image-save
@item i o @item i o
Save the image to a file (@code{image-save}). Save the image to a file (@code{image-save}).
@findex image-crop
@item i c @item i c
Interactively crop the image (@code{image-crop}). Crop the image interactively (@code{image-crop}).
@findex image-cut
@item i x @item i x
Interactively cut a rectangle from the image (@code{image-cut}). Cut a rectangle from the image interactively (@code{image-cut}).
@end table @end table
@xref{Image Mode,,, emacs, The GNU Emacs Manual}, for more details The size and rotation commands are ``repeating'', which means that you
about these image-specific key bindings. can continue adjusting the image without using the @kbd{i} prefix.
@node Multi-Frame Images @node Multi-Frame Images
@subsection Multi-Frame Images @subsection Multi-Frame Images

View file

@ -3390,7 +3390,7 @@ first, before handlers for jobs such as remote file access.
@code{file-directory-p}, @code{file-directory-p},
@code{file-equal-p}, @code{file-equal-p},
@code{file-executable-p}, @code{file-exists-p}, @code{file-executable-p}, @code{file-exists-p},
@code{file-group-gid}, @code{file-in-directory-p}, @code{file-in-directory-p},
@code{file-local-copy}, @code{file-locked-p}, @code{file-local-copy}, @code{file-locked-p},
@code{file-modes}, @code{file-name-all-completions}, @code{file-modes}, @code{file-name-all-completions},
@code{file-name-as-directory}, @code{file-name-as-directory},
@ -3452,7 +3452,7 @@ first, before handlers for jobs such as remote file access.
@code{file-direc@discretionary{}{}{}tory-p}, @code{file-direc@discretionary{}{}{}tory-p},
@code{file-equal-p}, @code{file-equal-p},
@code{file-executable-p}, @code{file-exists-p}, @code{file-executable-p}, @code{file-exists-p},
@code{file-group-gid}, @code{file-in-directory-p}, @code{file-in-directory-p},
@code{file-local-copy}, @code{file-locked-p}, @code{file-local-copy}, @code{file-locked-p},
@code{file-modes}, @code{file-name-all-completions}, @code{file-modes}, @code{file-name-all-completions},
@code{file-name-as-directory}, @code{file-name-as-directory},

View file

@ -3577,7 +3577,7 @@ the mouse position list will be @code{nil} if the value is
@code{drag-source}. This is useful to determine if a frame is not @code{drag-source}. This is useful to determine if a frame is not
directly visible underneath the mouse pointer. directly visible underneath the mouse pointer.
The @code{track-mouse} macro causes Emacs to generate mouse motion The @code{track-mouse} form causes Emacs to generate mouse motion
events by binding the variable @code{track-mouse} to a events by binding the variable @code{track-mouse} to a
non-@code{nil} value. If that variable has the special value non-@code{nil} value. If that variable has the special value
@code{dragging}, it additionally instructs the display engine to @code{dragging}, it additionally instructs the display engine to
@ -4112,7 +4112,7 @@ has the same meaning as the @var{action} argument to
Emacs implements receiving text and URLs individually for each Emacs implements receiving text and URLs individually for each
window system, and does not by default support receiving other kinds window system, and does not by default support receiving other kinds
of data as drops. To support receiving other kinds of data, use the of data as drops. To support receiving other kinds of data, use the
X-specific interface described below. X-specific interface described below:
@vindex x-dnd-test-function @vindex x-dnd-test-function
@vindex x-dnd-known-types @vindex x-dnd-known-types
@ -4141,71 +4141,29 @@ depending on the specific drag-and-drop protocol being used. For
example, the data type used for plain text may be either example, the data type used for plain text may be either
@code{"STRING"} or @code{"text/plain"}. @code{"STRING"} or @code{"text/plain"}.
@cindex XDS
@cindex direct save protocol
@vindex x-dnd-direct-save-function @vindex x-dnd-direct-save-function
When Emacs runs on X window system, it supports the X Direct Save @c FIXME: This description is overly-complicated and confusing. In
(@acronym{XDS}) protocol, which allows users to save a file by @c particular, the two calls to the function basically sound
dragging and dropping it onto an Emacs window, such as a Dired window. @c identical, so it is unclear how should the function distinguish
To comply with the unique requirements of @acronym{XDS}, these @c between the first and the second one. The description of who asks
drag-and-drop requests are processed specially: instead of being @c whom to do what is also very hard to understand. Needs rewording,
handled according to @code{x-dnd-types-alist}, they are handled by the @c and needs shorter sentences. Perhaps examples could help.
@dfn{direct-save function} that is the value of the variable However, @code{x-dnd-types-alist} does not handle a special kind of
@code{x-dnd-direct-save-function}. The value should be a function of drop sent by a program that wants Emacs to tell it where to save a
two arguments, @var{need-name} and @var{filename}. The @acronym{XDS} file in a specific location determined by the user. These drops are
protocol uses a two-step procedure for dragging files: instead handled by a function that is the value of the variable
@code{x-dnd-direct-save-function}. This function should accept two arguments.
@enumerate 1 If the first argument is non-@code{nil}, then the second argument is a
@item file name to save (with leading directories) that the other
The application from which the file is dragged asks Emacs to provide program recommends, and the
the full file name under which to save the file. For this purpose, function should return the full file name under which it should be
the direct-save function is called with its first argument saved. After the function completes, Emacs will ask the other program
@var{need-name} non-@code{nil}, and the second argument @var{filename} to save the file under the name that was returned, and if the file was
set to the basename of the file to be saved. It should return the successfully saved, call the function again with the first argument
fully-expanded absolute file name under which to save the file. For set to a non-@code{nil} value and the second argument set to the file
example, if a file is dragged to a Dired window, the natural directory name that was returned. The function should then perform whatever
for the file is the directory of the file shown at location of the action is appropriate (i.e., opening the file or refreshing a
drop. If saving the file is not possible for some reason, the directory listing.)
function should return @code{nil}, which will cancel the drag-and-drop
operation.
@item
The application from which the file is dragged saves the file under
the name returned by the first call to the direct-save function. If
it succeeds in saving the file, the direct-save function is called
again, this time with the first argument @var{need-name} set to
@code{nil} and the second argument @var{filename} set to the full
absolute name of the saved file. The function is then expected to do
whatever is needed given the fact that file was saved. For example,
Dired should update the directory on display by showing the new file
there.
@end enumerate
The default value of @code{x-dnd-direct-save-function} is
@code{x-dnd-save-direct}.
@defun x-dnd-save-direct need-name filename
When called with the @var{need-name} argument non-@code{nil}, this
function prompts the user for the absolute file name under which it
should be saved. If the specified file already exists, it
additionally asks the user whether to overwrite it, and returns the
absolute file name only if the user confirms the overwriting.
When called with the @var{need-name} argument @code{nil}, it reverts
the Dired listing if the current buffer is in Dired mode or one of its
descendants, and otherwise visits the file by calling @code{find-file}
(@pxref{Visiting Functions}).
@end defun
@defun x-dnd-save-direct-immediately need-name filename
This function works like @code{x-dnd-save-direct}, but when called
with its @var{need-name} argument non-@code{nil}, it doesn't prompt
the user for the full name of the file to be saved; instead, it
returns its argument @var{filename} expanded against the current
buffer's default directory (@pxref{File Name Expansion}). (It still
asks for confirmation if a file by that name already exists in the
default directory.)
@end defun
@cindex initiating drag-and-drop @cindex initiating drag-and-drop
On capable window systems, Emacs also supports dragging contents On capable window systems, Emacs also supports dragging contents

View file

@ -593,8 +593,8 @@ symbol a function definition, its function cell is said to be
In practice, nearly all functions have names, and are referred to by In practice, nearly all functions have names, and are referred to by
their names. You can create a named Lisp function by defining a their names. You can create a named Lisp function by defining a
lambda expression and putting it in a function cell (@pxref{Function lambda expression and putting it in a function cell (@pxref{Function
Cells}). However, it is more common to use the @code{defun} macro, Cells}). However, it is more common to use the @code{defun} special
described in the next section. form, described in the next section.
@ifnottex @ifnottex
@xref{Defining Functions}. @xref{Defining Functions}.
@end ifnottex @end ifnottex
@ -2631,12 +2631,6 @@ so the byte compiler can ignore calls whose value is ignored. This is
the same as the @code{side-effect-free} property of the function's the same as the @code{side-effect-free} property of the function's
symbol, @pxref{Standard Properties}. symbol, @pxref{Standard Properties}.
@item (important-return-value @var{val})
If @var{val} is non-@code{nil}, the byte compiler will warn about
calls to this function that do not use the returned value. This is the
same as the @code{important-return-value} property of the function's
symbol, @pxref{Standard Properties}.
@item (speed @var{n}) @item (speed @var{n})
Specify the value of @code{native-comp-speed} in effect for native Specify the value of @code{native-comp-speed} in effect for native
compilation of this function (@pxref{Native-Compilation Variables}). compilation of this function (@pxref{Native-Compilation Variables}).
@ -2699,14 +2693,13 @@ byte compiler can check that the calls match the declaration.
Tell the byte compiler to assume that @var{function} is defined in the Tell the byte compiler to assume that @var{function} is defined in the
file @var{file}. The optional third argument @var{arglist} is either file @var{file}. The optional third argument @var{arglist} is either
@code{t}, meaning the argument list is unspecified, or a list of @code{t}, meaning the argument list is unspecified, or a list of
formal parameters in the same style as @code{defun} (including the formal parameters in the same style as @code{defun}. An omitted
parentheses). An omitted @var{arglist} defaults to @code{t}, not @var{arglist} defaults to @code{t}, not @code{nil}; this is atypical
@code{nil}; this is atypical behavior for omitted arguments, and it behavior for omitted arguments, and it means that to supply a fourth
means that to supply a fourth but not third argument one must specify but not third argument one must specify @code{t} for the third-argument
@code{t} for the third-argument placeholder instead of the usual placeholder instead of the usual @code{nil}. The optional fourth
@code{nil}. The optional fourth argument @var{fileonly} argument @var{fileonly} non-@code{nil} means check only that
non-@code{nil} means check only that @var{file} exists, not that it @var{file} exists, not that it actually defines @var{function}.
actually defines @var{function}.
@end defmac @end defmac
@findex check-declare-file @findex check-declare-file

View file

@ -768,8 +768,8 @@ prefix definition, and then by those from the global map.
In the following example, we make @kbd{C-p} a prefix key in the local In the following example, we make @kbd{C-p} a prefix key in the local
keymap, in such a way that @kbd{C-p} is identical to @kbd{C-x}. Then keymap, in such a way that @kbd{C-p} is identical to @kbd{C-x}. Then
the binding for @kbd{C-p C-f} is the function @code{find-file}, just the binding for @kbd{C-p C-f} is the function @code{find-file}, just
like @kbd{C-x C-f}. By contrast, the key sequence @kbd{C-p 9} is not like @kbd{C-x C-f}. The key sequence @kbd{C-p 6} is not found in any
found in any active keymap. active keymap.
@example @example
@group @group
@ -778,14 +778,15 @@ found in any active keymap.
@end group @end group
@group @group
(keymap-local-set "C-p" ctl-x-map) (keymap-local-set "C-p" ctl-x-map)
@result{} (keymap #^[nil nil keymap @dots{} @result{} nil
@end group @end group
@group @group
(keymap-lookup nil "C-p C-f") (keymap-binding "C-p C-f")
@result{} find-file @result{} find-file
@end group @end group
@group @group
(keymap-lookup nil "C-p 9") (keymap-binding "C-p 6")
@result{} nil @result{} nil
@end group @end group
@end example @end example
@ -882,7 +883,7 @@ Normally it ignores @code{overriding-local-map} and
then it pays attention to them. @var{position} can optionally be either then it pays attention to them. @var{position} can optionally be either
an event position as returned by @code{event-start} or a buffer an event position as returned by @code{event-start} or a buffer
position, and may change the keymaps as described for position, and may change the keymaps as described for
@code{keymap-lookup} (@pxref{Functions for Key Lookup, keymap-lookup}). @code{keymap-binding}.
@end defun @end defun
@node Searching Keymaps @node Searching Keymaps
@ -1307,11 +1308,7 @@ the second example.
@end group @end group
@end example @end example
The @var{keymap} argument can be @code{nil}, meaning to look up The @var{keymap} argument can also be a list of keymaps.
@var{key} in the current keymaps (as returned by
@code{current-active-maps}, @pxref{Active Keymaps}); or it can be a
keymap or a list of keymaps, meaning to look up @var{key} only in the
specified keymaps.
Unlike @code{read-key-sequence}, this function does not modify the Unlike @code{read-key-sequence}, this function does not modify the
specified events in ways that discard information (@pxref{Key Sequence specified events in ways that discard information (@pxref{Key Sequence

View file

@ -1224,15 +1224,7 @@ x
@end example @end example
However, the other arguments (all but the last) should be mutable However, the other arguments (all but the last) should be mutable
lists. They can be dotted lists, whose last @sc{cdr}s are then lists.
replaced with the next argument:
@example
@group
(nconc (cons 1 2) (cons 3 (cons 4 5)) 'z)
@result{} (1 3 4 . z)
@end group
@end example
A common pitfall is to use a constant list as a non-last argument to A common pitfall is to use a constant list as a non-last argument to
@code{nconc}. If you do this, the resulting behavior is undefined @code{nconc}. If you do this, the resulting behavior is undefined

View file

@ -1338,7 +1338,7 @@ specified @var{file} and perform the necessary initialization of the
module. This is the primitive which makes sure the module exports the module. This is the primitive which makes sure the module exports the
@code{plugin_is_GPL_compatible} symbol, calls the module's @code{plugin_is_GPL_compatible} symbol, calls the module's
@code{emacs_module_init} function, and signals an error if that @code{emacs_module_init} function, and signals an error if that
function returns an error indication, or if the user typed @kbd{C-g} function returns an error indication, or if the use typed @kbd{C-g}
during the initialization. If the initialization succeeds, during the initialization. If the initialization succeeds,
@code{module-load} returns @code{t}. Note that @var{file} must @code{module-load} returns @code{t}. Note that @var{file} must
already have the proper file-name extension, as this function doesn't already have the proper file-name extension, as this function doesn't

View file

@ -4155,7 +4155,7 @@ Other keywords are optional:
@end multitable @end multitable
Lisp programs mark patterns in @var{query} with capture names (names Lisp programs mark patterns in @var{query} with capture names (names
that start with @code{@@}), and tree-sitter will return matched nodes that starts with @code{@@}), and tree-sitter will return matched nodes
tagged with those same capture names. For the purpose of tagged with those same capture names. For the purpose of
fontification, capture names in @var{query} should be face names like fontification, capture names in @var{query} should be face names like
@code{font-lock-keyword-face}. The captured node will be fontified @code{font-lock-keyword-face}. The captured node will be fontified

View file

@ -219,25 +219,17 @@ creates huge integers.
@cindex @acronym{IEEE} floating point @cindex @acronym{IEEE} floating point
Floating-point numbers are useful for representing numbers that are Floating-point numbers are useful for representing numbers that are
not integral. The range of floating-point numbers is the same as the not integral. The range of floating-point numbers is
range of the C data type @code{double} on the machine you are using. the same as the range of the C data type @code{double} on the machine
On almost all computers supported by Emacs, this is @acronym{IEEE} you are using. On all computers supported by Emacs, this is
binary64 floating point format, which is standardized by @acronym{IEEE} binary64 floating point format, which is standardized by
@url{https://standards.ieee.org/standard/754-2019.html,,IEEE Std @url{https://standards.ieee.org/standard/754-2019.html,,IEEE Std 754-2019}
754-2019} and is discussed further in David Goldberg's paper and is discussed further in David Goldberg's paper
``@url{https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html, ``@url{https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html,
What Every Computer Scientist Should Know About Floating-Point What Every Computer Scientist Should Know About Floating-Point Arithmetic}''.
Arithmetic}''. On modern platforms, floating-point operations follow On modern platforms, floating-point operations follow the IEEE-754
the IEEE-754 standard closely; however, results are not always rounded standard closely; however, results are not always rounded correctly on
correctly on some systems, notably 32-bit x86. some obsolescent platforms, notably 32-bit x86.
On some old computer systems, Emacs may not use IEEE floating-point.
We know of one such system on which Emacs runs correctly, but does not
follow IEEE-754: the VAX running NetBSD using GCC 10.4.0, where the
VAX @samp{D_Floating} format is used instead. IBM System/370-derived
mainframes and their XL/C compiler are also capable of utilizing a
hexadecimal floating point format, but Emacs has not yet been built in
such a configuration.
The read syntax for floating-point numbers requires either a decimal The read syntax for floating-point numbers requires either a decimal
point, an exponent, or both. Optional signs (@samp{+} or @samp{-}) point, an exponent, or both. Optional signs (@samp{+} or @samp{-})
@ -270,10 +262,6 @@ two NaNs as equal when their
signs and significands agree. Significands of NaNs are signs and significands agree. Significands of NaNs are
machine-dependent, as are the digits in their string representation. machine-dependent, as are the digits in their string representation.
NaNs are not available on systems which do not use IEEE
floating-point arithmetic; if the read syntax for a NaN is used on a
VAX, for example, the reader signals an error.
When NaNs and signed zeros are involved, non-numeric functions like When NaNs and signed zeros are involved, non-numeric functions like
@code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and @code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and
@code{gethash} determine whether values are indistinguishable, not @code{gethash} determine whether values are indistinguishable, not
@ -754,10 +742,9 @@ by rounding the quotient towards zero after each division.
@cindex @code{arith-error} in division @cindex @code{arith-error} in division
If you divide an integer by the integer 0, Emacs signals an If you divide an integer by the integer 0, Emacs signals an
@code{arith-error} error (@pxref{Errors}). On systems using IEEE-754 @code{arith-error} error (@pxref{Errors}). Floating-point division of
floating-point, floating-point division of a nonzero number by zero a nonzero number by zero yields either positive or negative infinity
yields either positive or negative infinity (@pxref{Float Basics}); (@pxref{Float Basics}).
otherwise, an @code{arith-error} is signaled as usual.
@end defun @end defun
@defun % dividend divisor @defun % dividend divisor

View file

@ -182,9 +182,7 @@ is over, and, together with @code{before-init-time}, provides the
measurement of how long it took. measurement of how long it took.
@item @item
It runs the normal hooks @code{after-init-hook} and It runs the normal hook @code{after-init-hook}.
@code{delayed-warnings-hook}. The latter shows any warnings emitted
during previous stages of startup, which are automatically delayed.
@item @item
If the buffer @file{*scratch*} exists and is still in Fundamental mode If the buffer @file{*scratch*} exists and is still in Fundamental mode
@ -1290,22 +1288,12 @@ the remote connection has no associated user, it will instead return
@end defun @end defun
@cindex GID @cindex GID
@defun group-real-gid
This function returns the real @acronym{GID} of the Emacs process.
@end defun
@defun group-gid @defun group-gid
This function returns the effective @acronym{GID} of the Emacs process. This function returns the effective @acronym{GID} of the Emacs process.
@end defun @end defun
@defun file-group-gid @defun group-real-gid
This function returns the connection-local value for the user's This function returns the real @acronym{GID} of the Emacs process.
effective @acronym{GID}. Similar to @code{file-user-uid}, if
@code{default-directory} is local, this is equivalent to
@code{group-gid}, but for remote files (@pxref{Remote Files, , ,
emacs, The GNU Emacs Manual}), it will return the @acronym{GID} for
the user associated with that remote connection; if the remote
connection has no associated user, it will instead return -1.
@end defun @end defun
@defun system-users @defun system-users

View file

@ -1755,9 +1755,7 @@ caught automatically, so that it doesn't stop the execution of whatever
program was running when the filter function was started. However, if program was running when the filter function was started. However, if
@code{debug-on-error} is non-@code{nil}, errors are not caught. @code{debug-on-error} is non-@code{nil}, errors are not caught.
This makes it possible to use the Lisp debugger to debug filter This makes it possible to use the Lisp debugger to debug filter
functions. @xref{Debugger}. If an error is caught, Emacs pauses for functions. @xref{Debugger}.
@code{process-error-pause-time} seconds so that the user sees the
error. @xref{Asynchronous Processes}
Many filter functions sometimes (or always) insert the output in the Many filter functions sometimes (or always) insert the output in the
process's buffer, mimicking the actions of the default filter. process's buffer, mimicking the actions of the default filter.
@ -2161,9 +2159,7 @@ automatically, so that it doesn't stop the execution of whatever
programs was running when the sentinel was started. However, if programs was running when the sentinel was started. However, if
@code{debug-on-error} is non-@code{nil}, errors are not caught. @code{debug-on-error} is non-@code{nil}, errors are not caught.
This makes it possible to use the Lisp debugger to debug the This makes it possible to use the Lisp debugger to debug the
sentinel. @xref{Debugger}. If an error is caught, Emacs pauses for sentinel. @xref{Debugger}.
@code{process-error-pause-time} seconds so that the user sees the
error. @xref{Asynchronous Processes}
While a sentinel is running, the process sentinel is temporarily While a sentinel is running, the process sentinel is temporarily
set to @code{nil} so that the sentinel won't run recursively. set to @code{nil} so that the sentinel won't run recursively.

View file

@ -376,43 +376,45 @@ is less than @var{c}, then @var{a} must be less than @var{c}. If you
use a comparison function which does not meet these requirements, the use a comparison function which does not meet these requirements, the
result of @code{sort} is unpredictable. result of @code{sort} is unpredictable.
The destructive aspect of @code{sort} for lists is that it reuses the The destructive aspect of @code{sort} for lists is that it rearranges the
cons cells forming @var{sequence} by changing their contents, possibly cons cells forming @var{sequence} by changing @sc{cdr}s. A nondestructive
rearranging them in a different order. This means that the value of sort function would create new cons cells to store the elements in their
the input list is undefined after sorting; only the list returned by sorted order. If you wish to make a sorted copy without destroying the
@code{sort} has a well-defined value. Example: original, copy it first with @code{copy-sequence} and then sort.
Sorting does not change the @sc{car}s of the cons cells in @var{sequence};
the cons cell that originally contained the element @code{a} in
@var{sequence} still has @code{a} in its @sc{car} after sorting, but it now
appears in a different position in the list due to the change of
@sc{cdr}s. For example:
@example @example
@group @group
(setq nums (list 2 1 4 3 0)) (setq nums (list 1 3 2 6 5 4 0))
(sort nums #'<) @result{} (1 3 2 6 5 4 0)
@result{} (0 1 2 3 4)
; nums is unpredictable at this point
@end group @end group
@end example
Most often we store the result back into the variable that held the
original list:
@example
(setq nums (sort nums #'<))
@end example
If you wish to make a sorted copy without destroying the original,
copy it first and then sort:
@example
@group @group
(setq nums (list 2 1 4 3 0)) (sort nums #'<)
(sort (copy-sequence nums) #'<) @result{} (0 1 2 3 4 5 6)
@result{} (0 1 2 3 4)
@end group @end group
@group @group
nums nums
@result{} (2 1 4 3 0) @result{} (1 2 3 4 5 6)
@end group @end group
@end example @end example
@noindent
@strong{Warning}: Note that the list in @code{nums} no longer contains
0; this is the same cons cell that it was before, but it is no longer
the first one in the list. Don't assume a variable that formerly held
the argument now holds the entire sorted list! Instead, save the result
of @code{sort} and use that. Most often we store the result back into
the variable that held the original list:
@example
(setq nums (sort nums #'<))
@end example
For the better understanding of what stable sort is, consider the following For the better understanding of what stable sort is, consider the following
vector example. After sorting, all items whose @code{car} is 8 are grouped vector example. After sorting, all items whose @code{car} is 8 are grouped
at the beginning of @code{vector}, but their relative order is preserved. at the beginning of @code{vector}, but their relative order is preserved.

View file

@ -643,12 +643,6 @@ ignore a call whose value is unused. If the property's value is
calls. In addition to byte compiler optimizations, this property is calls. In addition to byte compiler optimizations, this property is
also used for determining function safety (@pxref{Function Safety}). also used for determining function safety (@pxref{Function Safety}).
@item important-return-value
@cindex @code{important-return-value} property
A non-@code{nil} value makes the byte compiler warn about code that
calls the named function without using its returned value. This is
useful for functions where doing so is likely to be a mistake.
@item undo-inhibit-region @item undo-inhibit-region
If non-@code{nil}, the named function prevents the @code{undo} operation If non-@code{nil}, the named function prevents the @code{undo} operation
from being restricted to the active region, if @code{undo} is invoked from being restricted to the active region, if @code{undo} is invoked

View file

@ -5510,7 +5510,7 @@ contents of an SQLite database.
@section Parsing HTML and XML @section Parsing HTML and XML
@cindex parsing html @cindex parsing html
Emacs can be compiled with built-in @file{libxml2} support. Emacs can be compiled with built-in libxml2 support.
@defun libxml-available-p @defun libxml-available-p
This function returns non-@code{nil} if built-in libxml2 support is This function returns non-@code{nil} if built-in libxml2 support is
@ -5529,10 +5529,8 @@ mistakes.
If @var{start} or @var{end} are @code{nil}, they default to the values If @var{start} or @var{end} are @code{nil}, they default to the values
from @code{point-min} and @code{point-max}, respectively. from @code{point-min} and @code{point-max}, respectively.
The optional argument @var{base-url}, if non-@code{nil}, should be The optional argument @var{base-url}, if non-@code{nil}, should be a
used for warnings and errors reported by the @file{libxml2} library, string specifying the base URL for relative URLs occurring in links.
but Emacs currently calls the library with errors and warnings
disabled, so this argument is not used.
If the optional argument @var{discard-comments} is non-@code{nil}, If the optional argument @var{discard-comments} is non-@code{nil},
any top-level comment is discarded. (This argument is obsolete and any top-level comment is discarded. (This argument is obsolete and

View file

@ -1183,16 +1183,13 @@ wants the current value of a variable, it looks first in the lexical
environment; if the variable is not specified in there, it looks in environment; if the variable is not specified in there, it looks in
the symbol's value cell, where the dynamic value is stored. the symbol's value cell, where the dynamic value is stored.
(Internally, the lexical environment is a list whose members are (Internally, the lexical environment is an alist of symbol-value
usually cons cells that are symbol-value pairs, but some of its pairs, with the final element in the alist being the symbol @code{t}
members can be symbols rather than cons cells. A symbol in the list rather than a cons cell. Such an alist can be passed as the second
means the lexical environment declared that symbol's variable as argument to the @code{eval} function, in order to specify a lexical
locally considered to be dynamically bound. This list can be passed environment in which to evaluate a form. @xref{Eval}. Most Emacs
as the second argument to the @code{eval} function, in order to Lisp programs, however, should not interact directly with lexical
specify a lexical environment in which to evaluate a form. environments in this way; only specialized programs like debuggers.)
@xref{Eval}. Most Emacs Lisp programs, however, should not interact
directly with lexical environments in this way; only specialized
programs like debuggers.)
@cindex closures, example of using @cindex closures, example of using
Lexical bindings have indefinite extent. Even after a binding Lexical bindings have indefinite extent. Even after a binding
@ -2561,9 +2558,6 @@ documentation as @var{base-variable} has, if any, unless
the documentation of the variable at the end of the chain of aliases. the documentation of the variable at the end of the chain of aliases.
This function returns @var{base-variable}. This function returns @var{base-variable}.
If the resulting variable definition chain would be circular, then
Emacs will signal a @code{cyclic-variable-indirection} error.
@end defun @end defun
Variable aliases are convenient for replacing an old name for a Variable aliases are convenient for replacing an old name for a
@ -2612,6 +2606,9 @@ look like:
This function returns the variable at the end of the chain of aliases This function returns the variable at the end of the chain of aliases
of @var{variable}. If @var{variable} is not a symbol, or if @var{variable} is of @var{variable}. If @var{variable} is not a symbol, or if @var{variable} is
not defined as an alias, the function returns @var{variable}. not defined as an alias, the function returns @var{variable}.
This function signals a @code{cyclic-variable-indirection} error if
there is a loop in the chain of symbols.
@end defun @end defun
@example @example

View file

@ -3216,7 +3216,7 @@ any window it creates as dedicated to its buffer (@pxref{Dedicated
Windows}). It does that by calling @code{set-window-dedicated-p} with Windows}). It does that by calling @code{set-window-dedicated-p} with
the chosen window as first argument and the entry's value as second. the chosen window as first argument and the entry's value as second.
Side windows are by default dedicated with the value @code{side} Side windows are by default dedicated with the value @code{side}
(@pxref{Side Window Options and Functions}). ((@pxref{Side Window Options and Functions}).
@vindex preserve-size@r{, a buffer display action alist entry} @vindex preserve-size@r{, a buffer display action alist entry}
@item preserve-size @item preserve-size

View file

@ -5394,7 +5394,7 @@ a variable containing a vector of rules.
1: [merge, secsqr] 1: [a/x + b/x := (a + b)/x, ... ] 1: [merge, secsqr] 1: [a/x + b/x := (a + b)/x, ... ]
. . . .
' [merge,secsqr] @key{RET} = ' [merge,sinsqr] @key{RET} =
@end group @end group
@end smallexample @end smallexample

View file

@ -330,7 +330,6 @@ Syntactic Symbols
* Multiline Macro Symbols:: * Multiline Macro Symbols::
* Objective-C Method Symbols:: * Objective-C Method Symbols::
* Java Symbols:: * Java Symbols::
* Constraint Symbols::
* Statement Block Symbols:: * Statement Block Symbols::
* K&R Symbols:: * K&R Symbols::
@ -4235,9 +4234,6 @@ The first line in a ``topmost'' definition. @ref{Function Symbols}.
Topmost definition continuation lines. This is only used in the parts Topmost definition continuation lines. This is only used in the parts
that aren't covered by other symbols such as @code{func-decl-cont} and that aren't covered by other symbols such as @code{func-decl-cont} and
@code{knr-argdecl}. @ref{Function Symbols}. @code{knr-argdecl}. @ref{Function Symbols}.
@item constraint-cont
Continuation line of a topmost C++20 concept or requires clause.
@ref{Constraint Symbols}.
@item annotation-top-cont @item annotation-top-cont
Topmost definition continuation lines where all previous items are Topmost definition continuation lines where all previous items are
annotations. @ref{Java Symbols}. annotations. @ref{Java Symbols}.
@ -4401,7 +4397,6 @@ Java. @ref{Java Symbols}.
* Multiline Macro Symbols:: * Multiline Macro Symbols::
* Objective-C Method Symbols:: * Objective-C Method Symbols::
* Java Symbols:: * Java Symbols::
* Constraint Symbols::
* Statement Block Symbols:: * Statement Block Symbols::
* K&R Symbols:: * K&R Symbols::
@end menu @end menu
@ -5075,39 +5070,6 @@ the current line. Similarly, line 4 is assigned the @code{annotation-var-cont}
syntax due to it being a continuation of a variable declaration where preceding syntax due to it being a continuation of a variable declaration where preceding
the declaration is an annotation. the declaration is an annotation.
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@node Constraint Symbols
@subsection C++ Constraint Symbols
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
The C++20 standard introduced the notion of @dfn{concepts} and
@dfn{requirements}, a typical instance of which looks something like
this:
@example
1: template <typename T>
2: requires
3: requires (T t) @{
4: @{ ++t; @}
5: @}
6: && std::is_integral<T>
7: int foo();
@end example
@ssindex constraint-cont
Line 1 is assigned the familiar @code{topmost-intro}. Line 2 gets
@code{topmost-intro-cont}, being the keyword which introduces a
@dfn{requires clause}. Lines 3, 6, and 7 are assigned the syntax
@code{constraint-cont}, being continuations of the requires clause
started on line 2. Lines 4 and 5 get the syntaxes
@code{defun-block-intro} and @code{defun-close}, being analyzed as
though part of a function.
Note that the @code{requires} on Line 3 begins a @dfn{requires
expression}, not a a requires clause, hence its components are not
assigned @code{constraint-cont}. See
@url{https://en.cppreference.com/w/cpp/language/requires}.
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@node Statement Block Symbols @node Statement Block Symbols
@subsection Statement Block Symbols @subsection Statement Block Symbols

View file

@ -3133,23 +3133,13 @@ example, you can put the following in your init file:
To avoid the slightly distracting visual effect of Emacs starting with To avoid the slightly distracting visual effect of Emacs starting with
its default frame size and then growing to fullscreen, you can add an its default frame size and then growing to fullscreen, you can add an
@samp{Emacs.Geometry} entry to the Windows Registry settings. @xref{X @samp{Emacs.Geometry} entry to the Windows registry settings.
Resources,,, emacs, The GNU Emacs Manual}. To compute the correct @xref{X Resources,,, emacs, The GNU Emacs Manual}.
values for width and height you use in the Registry settings, first
maximize the Emacs frame and then evaluate @code{(frame-height)} and To compute the correct values for width and height, first maximize the
Emacs frame and then evaluate @code{(frame-height)} and
@code{(frame-width)} with @kbd{M-:}. @code{(frame-width)} with @kbd{M-:}.
Alternatively, you can avoid the visual effect of Emacs changing its
frame size entirely in your init file (i.e., without using the
Registry), like this:
@lisp
(setq frame-resize-pixelwise t)
(set-frame-position nil 0 0)
(set-frame-size nil (display-pixel-width) (display-pixel-height) t)
@end lisp
@node Emacs in a Linux console @node Emacs in a Linux console
@section How can I alleviate the limitations of the Linux console? @section How can I alleviate the limitations of the Linux console?
@cindex Console, Linux console, TTY, fbterm @cindex Console, Linux console, TTY, fbterm

View file

@ -1265,7 +1265,7 @@ is serialized by Eglot to the following JSON text:
@chapter Troubleshooting Eglot @chapter Troubleshooting Eglot
@cindex troubleshooting Eglot @cindex troubleshooting Eglot
This chapter documents commands and variables that can be used to This section documents commands and variables that can be used to
troubleshoot Eglot problems. It also provides guidelines for troubleshoot Eglot problems. It also provides guidelines for
reporting Eglot bugs in a way that facilitates their resolution. reporting Eglot bugs in a way that facilitates their resolution.
@ -1275,15 +1275,7 @@ pop up special buffers that can be used to inspect the communications
between the Eglot and language server. In many cases, this will between the Eglot and language server. In many cases, this will
indicate the problems or at least provide a hint. indicate the problems or at least provide a hint.
@menu @cindex performance
* Performance::
* Getting the latest version::
* Reporting bugs::
@end menu
@node Performance
@section Performance
@cindex performance problems, with Eglot
A common and easy-to-fix cause of performance problems is the length A common and easy-to-fix cause of performance problems is the length
of the Eglot events buffer because it represent additional work that of the Eglot events buffer because it represent additional work that
Eglot must do. After verifying Eglot is operating correctly but Eglot must do. After verifying Eglot is operating correctly but
@ -1297,33 +1289,6 @@ techniques to improve their performance. Often, this can be tweaked
by changing the server configuration (@pxref{Advanced server by changing the server configuration (@pxref{Advanced server
configuration}). configuration}).
@node Getting the latest version
@section Getting the latest version
@cindex upgrading Eglot
To install the latest Eglot in an Emacs version that does not bundle
Eglot, use @kbd{M-x package-install}.
Often, a newer Eglot version exists that has fixed a longstanding bug,
has more LSP features, or just better supports a particular language
server. Recent Eglot versions can self-update via the command
@kbd{M-x eglot-upgrade-eglot}. This will replace any currently
installed version with the newest one available from the ELPA archives
configured in @code{package-archives}.
You can also update Eglot through other methods, such as
@code{use-package} (@pxref{Installing packages,,, use-package,
use-package User Manual}), @code{package-install},
@code{list-packages} or the newer @code{package-upgrade}
(@pxref{Packages,,, emacs, GNU Emacs Manual}). However, do read the
docstrings of the command you intend to use before you use it, as some
of them may not work in exactly the same way across Emacs versions,
meaning your configuration may be not portable.
@node Reporting bugs
@section Reporting bugs
@cindex bug reports
If you think you have found a bug, we want to hear about it. Before If you think you have found a bug, we want to hear about it. Before
reporting a bug, keep in mind that interaction with language servers reporting a bug, keep in mind that interaction with language servers
represents a large quantity of unknown variables. Therefore, it is represents a large quantity of unknown variables. Therefore, it is
@ -1367,10 +1332,6 @@ public Git repository.
Include versions of the software used. The Emacs version can be Include versions of the software used. The Emacs version can be
obtained with @kbd{M-x emacs-version}. obtained with @kbd{M-x emacs-version}.
We welcome bug reports about all Eglot versions, but it is helpful to
first check if the problem isn't already fixed in the latest version
(@pxref{Getting the latest version}).
It's also essential to include the version of ELPA packages that are It's also essential to include the version of ELPA packages that are
explicitly or implicitly loaded. The optional but popular Company or explicitly or implicitly loaded. The optional but popular Company or
Markdown packages are distributed as GNU ELPA packages, not to mention Markdown packages are distributed as GNU ELPA packages, not to mention

View file

@ -952,7 +952,7 @@ Here, ``password'' refers to your account password, which is usually
your @samp{NickServ} password. To make this work, customize your @samp{NickServ} password. To make this work, customize
@code{erc-sasl-user} and @code{erc-sasl-password} or specify the @code{erc-sasl-user} and @code{erc-sasl-password} or specify the
@code{:user} and @code{:password} keyword arguments when invoking @code{:user} and @code{:password} keyword arguments when invoking
@code{erc-tls}. @code{erc-tls}. Note that @code{:user} cannot be given interactively.
@item @code{external} (via Client TLS Certificate) @item @code{external} (via Client TLS Certificate)
This works in conjunction with the @code{:client-certificate} keyword This works in conjunction with the @code{:client-certificate} keyword
@ -1477,30 +1477,10 @@ questions. You can also try the relatively quiet @samp{#erc}, on the
same network, for more involved questions. same network, for more involved questions.
@item @item
@anchor{Upgrading}
You can check GNU ELPA between Emacs releases to see if a newer You can check GNU ELPA between Emacs releases to see if a newer
version is available that might contain a fix for your issue: version is available that might contain a fix for your issue:
@uref{https://elpa.gnu.org/packages/erc.html}. @uref{https://elpa.gnu.org/packages/erc.html}.
To upgrade, run @kbd{M-x list-packages @key{RET}}. In the
@file{*Packages*} (@code{package-menu-mode}) buffer, click the
@samp{erc} package link for the desired version. If unsure, or if the
version column is too narrow to tell, try the bottom-most candidate.
In the resulting @code{help-mode} buffer, confirm the version and
click @samp{Install}. Make sure to restart Emacs before reconnecting
to IRC, and don't forget that you can roll back to the previous
version by running @kbd{M-x package-delete @key{RET}}.
@xref{Packages,,,emacs, the Emacs manual} for more information.
In the rare instance you need an emergency fix or have volunteered to
test an edge feature between ERC releases, you can try adding
@samp{("devel" . "https://elpa.gnu.org/devel/")} to
@code{package-archives} prior to performing the steps above. For
this, you'll want to instead select a ``snapshot'' version from the
menu. Please be aware that when going this route, the latest changes
may not yet be available and you run the risk of incurring other bugs
and encountering unstable features.
@item @item
To report a bug in ERC, use @kbd{M-x erc-bug}. To report a bug in ERC, use @kbd{M-x erc-bug}.

View file

@ -602,8 +602,6 @@ disabled by default.
@cmindex egrep @cmindex egrep
@itemx fgrep @itemx fgrep
@cmindex fgrep @cmindex fgrep
@itemx rgrep
@cmindex rgrep
@itemx glimpse @itemx glimpse
@cmindex glimpse @cmindex glimpse
The @command{grep} commands are compatible with GNU @command{grep}, The @command{grep} commands are compatible with GNU @command{grep},

View file

@ -1,8 +1,8 @@
\input texinfo @c -*- mode: texinfo; coding: utf-8 -*- \input texinfo @c -*- mode: texinfo; coding: utf-8 -*-
@comment %**start of header @comment %**start of header
@setfilename ../../info/flymake.info @setfilename ../../info/flymake.info
@set VERSION 1.3.4 @set VERSION 1.2.2
@set UPDATED April 2023 @set UPDATED November 2021
@settitle GNU Flymake @value{VERSION} @settitle GNU Flymake @value{VERSION}
@include docstyle.texi @include docstyle.texi
@syncodeindex pg cp @syncodeindex pg cp
@ -142,12 +142,6 @@ highlighted regions to learn what the specific problem
is. Alternatively, place point on the highlighted regions and use the is. Alternatively, place point on the highlighted regions and use the
commands @code{eldoc} or @code{display-local-help}. commands @code{eldoc} or @code{display-local-help}.
Another easy way to get instant access to the diagnostic text is to
set @code{flymake-show-diagnostics-at-end-of-line} to a non-@code{nil}
value. This makes the diagnostic messages appear at the end of the
line where the regular annotation is located (@pxref{Customizable
variables})
@cindex next and previous diagnostic @cindex next and previous diagnostic
If the diagnostics are outside the visible region of the buffer, If the diagnostics are outside the visible region of the buffer,
@code{flymake-goto-next-error} and @code{flymake-goto-prev-error} are @code{flymake-goto-next-error} and @code{flymake-goto-prev-error} are
@ -320,22 +314,6 @@ Which fringe (if any) should show the warning/error bitmaps.
@item flymake-wrap-around @item flymake-wrap-around
If non-@code{nil}, moving to errors with @code{flymake-goto-next-error} and If non-@code{nil}, moving to errors with @code{flymake-goto-next-error} and
@code{flymake-goto-prev-error} wraps around buffer boundaries. @code{flymake-goto-prev-error} wraps around buffer boundaries.
@item flymake-show-diagnostics-at-end-of-line
If non-@code{nil}, show summarized descriptions of diagnostics at the
end of the line. Depending on your preference, this can either be
distracting and easily confused with actual code, or a significant
early aid that relieves you from moving around or reaching for the
mouse to consult an error message.
@item flymake-error-eol
A custom face for summarizing diagnostic error messages.
@item flymake-warning-eol
A custom face for summarizing diagnostic warning messages.
@item flymake-note-eol
A custom face for summarizing diagnostic notes.
@end vtable @end vtable
@node Extending Flymake @node Extending Flymake
@ -416,7 +394,7 @@ its @code{flymake-overlay-control} property:
@item @item
@cindex severity of diagnostic @cindex severity of diagnostic
@code{severity} is a non-negative integer specifying the @code{flymake-severity} is a non-negative integer specifying the
diagnostic's severity. The higher the value, the more serious is the diagnostic's severity. The higher the value, the more serious is the
error. If the overlay property @code{priority} is not specified in error. If the overlay property @code{priority} is not specified in
@code{flymake-overlay-control}, @code{flymake-severity} is used to set @code{flymake-overlay-control}, @code{flymake-severity} is used to set
@ -431,17 +409,6 @@ type, in case the name of the symbol associated with it is very long.
@vindex flymake-category @vindex flymake-category
@code{flymake-category} is a symbol whose property list is considered @code{flymake-category} is a symbol whose property list is considered
the default for missing values of any other properties. the default for missing values of any other properties.
@item
@cindex mode-line appearance of a diagnostic
@code{mode-line-face} is a face specifier controlling the appearance
of the indicator of this type of diagnostic in the mode line.
@item
@cindex summarized appearance of a diagnostic
@code{echo-face} is a face specifier controlling the appearance of the
summarized description of this diagnostic when reading diagnostic
messages (@pxref{Finding diagnostics}).
@end itemize @end itemize
@cindex predefined diagnostic types @cindex predefined diagnostic types

View file

@ -10528,9 +10528,9 @@ article (@code{gnus-summary-refer-references}).
@kindex A T @r{(Summary)} @kindex A T @r{(Summary)}
Display the full thread where the current article appears Display the full thread where the current article appears
(@code{gnus-summary-refer-thread}). By default this command looks for (@code{gnus-summary-refer-thread}). By default this command looks for
articles only in the current group. If the group belongs to a backend articles only in the current group. Some backends (currently only
that has an associated search engine, articles are found by searching. @code{nnimap}) know how to find articles in the thread directly. In
In other cases each header in the current group must be fetched and other cases each header in the current group must be fetched and
examined, so it usually takes a while. If you do it often, you may examined, so it usually takes a while. If you do it often, you may
consider setting @code{gnus-fetch-old-headers} to @code{invisible} consider setting @code{gnus-fetch-old-headers} to @code{invisible}
(@pxref{Filling In Threads}). This won't have any visible effects (@pxref{Filling In Threads}). This won't have any visible effects
@ -10538,22 +10538,19 @@ normally, but it'll make this command work a whole lot faster. Of
course, it'll make group entry somewhat slow. course, it'll make group entry somewhat slow.
@vindex gnus-refer-thread-use-search @vindex gnus-refer-thread-use-search
If @code{gnus-refer-thread-use-search} is @code{nil} (the default) If @code{gnus-refer-thread-use-search} is non-@code{nil} then those backends
then thread-referral only looks for articles in the current group. If that know how to find threads directly will search not just in the
this variable is @code{t} the server to which the current group current group but all groups on the same server.
belongs is searched (provided that searching is available for the
server's backend). If this variable is a list of servers, each server
in the list is searched.
@vindex gnus-refer-thread-limit @vindex gnus-refer-thread-limit
The @code{gnus-refer-thread-limit} variable says how many old (i.e., The @code{gnus-refer-thread-limit} variable says how many old (i.e.,
articles before the first displayed in the current group) headers to articles before the first displayed in the current group) headers to
fetch when referring a thread. The default is 500. If @code{t}, all fetch when doing this command. The default is 200. If @code{t}, all
the available headers will be fetched. This variable can be the available headers will be fetched. This variable can be overridden
overridden by giving the @kbd{A T} command a numerical prefix. by giving the @kbd{A T} command a numerical prefix.
@vindex gnus-refer-thread-limit-to-thread @vindex gnus-refer-thread-limit-to-thread
@code{gnus-summary-refer-thread} tries to add any articles it finds to In most cases @code{gnus-refer-thread} adds any articles it finds to
the current summary buffer. (When @code{gnus-refer-thread-use-search} the current summary buffer. (When @code{gnus-refer-thread-use-search}
is true and the initial referral starts from a summary buffer for a is true and the initial referral starts from a summary buffer for a
non-virtual group this may not be possible. In this case a new non-virtual group this may not be possible. In this case a new

View file

@ -1948,9 +1948,11 @@ requires the @acronym{POP}-before-@acronym{SMTP} authentication.
@cindex X-Message-SMTP-Method @cindex X-Message-SMTP-Method
If you have a complex @acronym{SMTP} setup, and want some messages to If you have a complex @acronym{SMTP} setup, and want some messages to
go via one mail server, and other messages to go through another, you go via one mail server, and other messages to go through another, you
can use the @samp{X-Message-SMTP-Method} header to override the can use the @samp{X-Message-SMTP-Method} header. These are the
default by using the keyword @samp{smtp} followed by the server supported values:
information:
@table @samp
@item smtpmail
@example @example
X-Message-SMTP-Method: smtp smtp.fsf.org 587 X-Message-SMTP-Method: smtp smtp.fsf.org 587
@ -1966,19 +1968,16 @@ This is the same as the above, but uses @samp{other-user} as the user
name when authenticating. This is handy if you have several name when authenticating. This is handy if you have several
@acronym{SMTP} accounts on the same server. @acronym{SMTP} accounts on the same server.
This header may also be used to specify an alternative MTA by using a @item sendmail
@samp{mailer} keyword, where @samp{mailer} is the name of an MTA with
a corresponding @code{message-send-mail-with-'mailer'} function. For
example:
@example @example
X-Message-SMTP-Method: sendmail X-Message-SMTP-Method: sendmail
@end example @end example
will send the message via the locally installed sendmail program. The This will send the message via the locally installed sendmail/exim/etc
recognized values of @samp{mailer} are sendmail, qmail, mh, and installation.
mailclient.
@end table
@item message-mh-deletable-headers @item message-mh-deletable-headers
@vindex message-mh-deletable-headers @vindex message-mh-deletable-headers

View file

@ -5958,9 +5958,8 @@ the agenda (see [[*Weekly/daily agenda]]). We distinguish:
#+findex: org-block #+findex: org-block
For more complex date specifications, Org mode supports using the For more complex date specifications, Org mode supports using the
special expression diary entries implemented in the special expression diary entries implemented in the Emacs Calendar
[[info:emacs#Special Diary Entries][Emacs Calendar package]][fn:20]. package[fn:20]. For example, with optional time:
For example, with optional time:
#+begin_example #+begin_example
,* 22:00-23:00 The nerd meeting on every 2nd Thursday of the month ,* 22:00-23:00 The nerd meeting on every 2nd Thursday of the month

View file

@ -938,16 +938,6 @@ be used.
This method does not support user names. This method does not support user names.
@item @option{flatpak}
@cindex method @option{flatpak}
@cindex @option{flatpak} method
Integration of Flatpak sandboxes. The host name may be either an
application ID, a sandbox instance ID, or a PID, as returned by
@samp{flatpak ps}.
This method does not support user names.
@end table @end table
@ -4377,6 +4367,7 @@ Flushes the current buffer's remote connection objects, the same as in
Flushes all active remote connection objects, the same as in Flushes all active remote connection objects, the same as in
@code{tramp-cleanup-connection}. This command removes also ad-hoc @code{tramp-cleanup-connection}. This command removes also ad-hoc
proxy definitions (@pxref{Ad-hoc multi-hops}). proxy definitions (@pxref{Ad-hoc multi-hops}).
@end deffn @end deffn
@deffn Command tramp-cleanup-all-buffers @deffn Command tramp-cleanup-all-buffers
@ -4385,20 +4376,6 @@ connections and ad-hoc proxy definition are cleaned up in addition to
killing all buffers related to remote connections. killing all buffers related to remote connections.
@end deffn @end deffn
@deffn Command tramp-cleanup-some-buffers
Similar to @code{tramp-cleanup-all-buffers}, where all remote
connections and ad-hoc proxy definition are cleaned up. However,
additional buffers are killed only if one of the functions in
@code{tramp-cleanup-some-buffers-hook} returns @code{t}.
@end deffn
@defopt tramp-cleanup-some-buffers-hook
The functions in this hook determine, whether a remote buffer is
killed when @code{tramp-cleanup-some-buffers} is called. Per default,
remote buffers which are linked to a remote file, remote @code{dired}
buffers, and buffers related to a remote process are cleaned up.
@end defopt
@node Renaming remote files @node Renaming remote files
@section Renaming remote files @section Renaming remote files

View file

@ -17,32 +17,6 @@ This refers to https://github.com/joaotavora/eglot/issues/. That is,
to look up issue github#1234, go to to look up issue github#1234, go to
https://github.com/joaotavora/eglot/issues/1234. https://github.com/joaotavora/eglot/issues/1234.
* Changes in Eglot 1.15 (29/4/2023)
** Fix LSP "languageId" detection
Many servers today support multiple languages, meaning they can handle
more than one file type in the same connection. This relies on the
client supplying a ':languageId' string. Previously, Eglot calculated
this string based on an imperfect heuristic and was often wrong. See
github#1206.
** Fix problems with missing signature documentation (bug#62687)
** Reworked 'eglot-imenu'
Eglot's Imenu backend (used for M-x imenu among other extensions), has
been reworked. Most newer servers respond to
'textDocument/documentSymbol' with a vector of 'DocumentSymbol', not
'SymbolInformation'. It's not worth it trying to make the two formats
resemble each other. This also lays groundwork supporting a
forthcoming "breadcrumb" feature of bug#58431.
** New command 'eglot-update'
This allows users to easily update to the latest version of Eglot.
* Changes in Eglot 1.14 (3/4/2023) * Changes in Eglot 1.14 (3/4/2023)
@ -96,16 +70,6 @@ been added to 'eglot-stay-out-of'.
** ELPA installations on Emacs 26.3 are supported again. ** ELPA installations on Emacs 26.3 are supported again.
* Changes in Eglot 1.12.29 (Eglot bundled with Emacs 29.1)
** Eglot can upgrade itself to the latest version.
The new command 'eglot-upgrade-eglot' works around behaviour in the
existing 'package-install' command and the new 'package-upgrade'
command which would prevent the user from easily grabbing the latest
version as usual.
* Changes in Eglot 1.12 (13/03/2023) * Changes in Eglot 1.12 (13/03/2023)
@ -129,7 +93,7 @@ The position-encoding scheme (UTF-8, UTF-16 or UTF-32) can now
be negotiated with the server. be negotiated with the server.
** More of the user's Eldoc configuration is respected. ** More of the user's Eldoc configuration is respected.
This change addresses the problems reported in many Eglot reports This change addresses the problems reported in many Elglot reports
dating back to early 2021 at least. dating back to early 2021 at least.
(github#646, github#894, github#920, github#1031, github#1171). (github#646, github#894, github#920, github#1031, github#1171).
@ -175,7 +139,7 @@ systems (bug#58790).
These modes are usually handled by the same server that handles the These modes are usually handled by the same server that handles the
"classical mode". "classical mode".
** New servers csharp-ls and texlab added to 'eglot-server-programs'. ** New servers chsharp-ls and texlab added to 'eglot-server-programs'.
** Assorted bugfixes. ** Assorted bugfixes.
(bug#59824, bug#59338) (bug#59824, bug#59338)

View file

@ -11,210 +11,6 @@ This file is about changes in ERC, the powerful, modular, and
extensible IRC (Internet Relay Chat) client distributed with extensible IRC (Internet Relay Chat) client distributed with
GNU Emacs since Emacs version 22.1. GNU Emacs since Emacs version 22.1.
* Changes in ERC 5.6
** Module 'keep-place' now offers a visual indicator.
Remember your place in ERC buffers a bit more easily while retaining
the freedom to look around. Optionally sync the indicator to any
progress made when you haven't yet caught up to the live stream. See
options 'erc-keep-place-indicator-style' and friends and new module
'keep-place-indicator', which for now must be added manually to
'erc-modules'.
** Module 'fill' now offers a style based on 'visual-line-mode'.
This fill style mimics the "hanging indent" look of 'erc-fill-static'
and provides some movement and editing commands to optionally tame the
less familiar aspects of 'visual-line' behavior. An interactive
helper called 'erc-fill-wrap-nudge' allows for dynamic "refilling" of
buffers on the fly. Set 'erc-fill-function' to 'erc-fill-wrap' to get
started.
** A unified interactive entry point.
New users are often dismayed to discover that M-x ERC doesn't connect
to its default network, Libera.Chat, over TLS. Though perhaps a
decade overdue, this is no longer the case. Other UX improvements in
this area aim to make the process of connecting interactively slightly
more streamlined and less repetitive, even for veteran users.
** Revised buffer-display handling for interactive commands.
A point of friction for new users and one only just introduced with
ERC 5.5 has been the lack of visual feedback when first connecting via
M-x erc or when issuing a "/JOIN" command at the prompt. As explained
below, in the news for 5.5, the discovery of a security issue led to
most new ERC buffers being "buried" on creation. On further
reflection, this was judged to have been an overcorrection in the case
of interactive invocations, hence the borrowing of an old option,
'erc-query-display', and the bestowing of a new alias,
'erc-interactive-display', which better describes its expanded role as
a more general buffer-display knob for interactive commands ("/QUERY"
still among them).
Accompanying this addition are "display"-suffixed aliases for related
options 'erc-join-buffer' and 'erc-auto-query', which users have
reported as being difficult to discover and remember. When the latter
option (now known as 'erc-receive-query-display') is nil, ERC uses
'erc-join-buffer' in its place, much like it does for
'erc-interactive-display'. The old nil behavior can still be gotten
via the new compatibility flag 'erc-receive-query-display-defer'.
** Setting a module's mode variable via Customize earns a warning.
Trying and failing to activate a module via its minor mode's Custom
widget has been an age-old annoyance for new users. Previously
ineffective, this method now actually works, but it also admonishes
users to edit the 'erc-modules' widget instead.
** The option 'erc-timestamp-use-align-to' is more versatile.
While this option has always offered to right-align stamps via the
'display' text property, it's now more effective at doing so when set
to a number indicating an offset from the right edge. And when set to
the symbol 'margin', it displays stamps in the right margin, although,
at the moment, this is mostly intended for use by other modules, such
as 'fill-wrap', described above. For both these variants, users of
the 'log' module may want to customize 'erc-log-filter-function' to
'erc-stamp-prefix-log-filter' to avoid ragged right-hand stamps
appearing in their saved logs.
** Smarter reconnect handling for users on the move.
ERC now offers a new, experimental reconnect strategy in the function
'erc-server-delayed-check-reconnect', which tests for underlying
connectivity before attempting to reconnect in earnest. See options
'erc-server-reconnect-function' and 'erc-nickname-in-use-functions' to
get started.
** Easily constrain all ERC-related business to a dedicated frame.
The option 'erc-reuse-frames' can now be set to 'displayed', which
tells ERC to show new buffers in frames already occupied by buffers
from the same connection. This customization depends on the option
'erc-buffer-display' (formerly 'erc-join-buffer') being set to
'frame'. If you find the name 'displayed' unhelpful, please suggest
an alternative by writing to the mailing list.
** Some keybindings are now set by modules rather than their libraries.
To put it another way, simply loading a built-in module's library no
longer modifies 'erc-mode-map'. Instead, modifications occur during
module setup. This should not impact most user configs since ERC
doesn't bother with keys already taken and only removes bindings it's
previously created. Note that while all affected bindings still
reside in 'erc-mode-map', future built-in modules will use their own
minor-mode maps, and new third-party modules should do the same.
** The option 'erc-timestamp-format-right' has been deprecated.
Having to account for this option prevented other ERC modules from
easily determining what right-hand stamps would look like before
insertion, which is knowledge needed for certain UI decisions. The
way ERC has chosen to address this is imperfect and boils down to
asking users who've customized this option to switch to
'erc-timestamp-format' instead. If you're affected by this and feel
that some other solution, like automatic migration, is justified,
please make that known on the bug list.
** The 'nicknames' entry in 'erc-button-alist' is officially exceptional.
It's no secret that the 'buttons' module treats potential nicknames
specially. To simplify ERC's move to next-gen "rich UI" extensions,
this special treatment is being canonized. From now on, all values
other than the symbol 'erc-button-buttonize-nicks' appearing in the
"FORM" field (third element) of this entry are considered deprecated
and will incur a warning.
** Option 'erc-query-on-unjoined-chan-privmsg' restored and renamed.
This option was accidentally removed from the default client in ERC
5.5 and was thus prevented from influencing PRIVMSG routing. It's now
been restored with a slightly revised role contingent on a few
assumptions explained in its doc string. For clarity, it has been
renamed 'erc-ensure-target-buffer-on-privmsg'.
** Miscellaneous UX changes.
Some minor quality-of-life niceties have finally made their way to
ERC. For example, the function 'erc-echo-timestamp' is now
interactive and can be invoked on any message to view its timestamp in
the echo area. The command 'erc-button-previous' now moves to the
beginning instead of the end of buttons. And the 'irccontrols' module
now supports additional colors and special handling for "spoilers"
(hidden text).
** Changes in the library API.
*** Some top-level dependencies have been removed.
The library 'erc-goodies' is no longer loaded by ERC's main library.
This was done to further cement the move toward a unidirectional
dependency flow begun in 5.5. Additionally, a few barely used and
newly introduced dependencies are now lazily loaded, which may upset
some third-party code. The first of these is 'pp' because its
'pp-to-string' is autoloaded in all supported ERC versions. Also gone
are 'thingatpt', 'time-date', and 'iso8601'. All were used ultra
sparingly, and the latter two have only been around for one minor
release cycle, so their removal hopefully won't cause much churn.
*** Some ERC-applied text properties have changed.
Chiefly, 'rear-sticky' has been replaced by 'erc-command', which
records the IRC command (or numeric) associated with a message. Less
impactfully, the value of the 'field' property for ERC's prompt has
changed from 't' to the more useful 'erc-prompt', although the
property of the same name has been retained.
*** ERC now manages timestamp-related properties a bit differently.
For starters, the 'cursor-sensor-functions' property no longer
contains unique closures and thus no longer proves effective for
traversing messages. To compensate, a new property, 'erc-timestamp',
now spans message bodies but not the newlines delimiting them.
Somewhat relatedly, the function 'erc-insert-aligned' has been
deprecated and removed from the primary client code path.
*** The role of a module's Custom group is now more clearly defined.
Associating built-in modules with Custom groups and provided library
features has improved. More specifically, a module's group now enjoys
the singular purpose of determining where the module's minor mode
variable lives in the Customize interface. And although ERC is now
slightly more adept at linking these entities, third-parties are still
encouraged to keep a module's name aligned with its group's as well as
the provided feature of its containing library, if only for the usual
reasons of namespace hygiene and discoverability.
*** ERC now supports arbitrary CHANTYPES.
Specifically, channels can be prefixed with any predesignated
character, mainly to afford more flexibility to specialty services,
like bridges to other protocols.
*** 'erc-cmd-HELP' recognizes subcommands.
Some IRC "slash" commands are hierarchical and require users to
specify a subcommand to actually carry out anything of consequence.
Built-in modules can now provide more detailed help for a particular
subcommand by telling ERC to defer to a specialized handler.
*** Longtime quasi modules have been made proper.
The 'fill' module is now defined by 'define-erc-module'. The same
goes for ERC's imenu integration, which has 'imenu' now appearing in
the default value of 'erc-modules'.
*** Prompt input is split before 'erc-pre-send-functions' has a say.
Hook members are now treated to input whose lines have already been
adjusted to fall within the allowed length limit. For convenience,
third-party code can request that the final input be "re-filled" prior
to being sent. See doc string for details.
*** ERC's prompt survives the insertion of user input and messages.
Previously, ERC's prompt and its input marker disappeared while
running hooks during message insertion, and the position of its
"insert marker" (ERC's per-buffer process mark) was inconsistent
during these spells. To make insertion handling more predictable in
preparation for incorporating various protocol extensions, the prompt
and its bounding markers have become perennial fixtures. In rare
cases, these changes may mean third-party code needs tweaking, for
example, requiring the use of 'insert-before-markers' instead of
'insert'. As always, users feeling unduly inconvenienced by these
changes are encouraged to voice their concerns on the bug list.
*** Miscellaneous changes
Two helper macros from GNU ELPA's Compat library are now available to
third-party modules as 'erc-compat-call' and 'erc-compat-function'.
In the area of buttons, 'Info-goto-node' has been supplanted by plain
old 'info' in 'erc-button-alist', and the bracketed "<URL:...>"
pattern entry has been removed because it was more or less redundant.
And the "TAB" key is now bound to a new command, 'erc-tab', that only
calls 'completion-at-point' when point is in the input area and
module-specific commands, like 'erc-button-next', otherwise.
* Changes in ERC 5.5 * Changes in ERC 5.5
@ -359,8 +155,8 @@ In an effort to help further tame ERC's complexity, the variable
'erc-default-recipients' is now expected to hold but a single target. 'erc-default-recipients' is now expected to hold but a single target.
As a consequence, functions like 'erc-add-default-channel' that As a consequence, functions like 'erc-add-default-channel' that
imagine an alternate, aspirational model of buffer-target relations imagine an alternate, aspirational model of buffer-target relations
have been deprecated. Grep for their names in ChangeLog.4 for have been deprecated. See Emacs change-log entries from around July
details. of 2022 for specifics.
A number of less consequential deprecations also debut in this A number of less consequential deprecations also debut in this
release. For example, the function 'erc-auto-query' was deemed too release. For example, the function 'erc-auto-query' was deemed too

View file

@ -89,9 +89,7 @@ Mathematics ∀ p ∈ world • hello p □
Meetei Mayek (ꯃꯤꯇꯩ ꯃꯌꯦꯛ) ꯈꯨꯔꯨꯝꯖꯔꯤ Meetei Mayek (ꯃꯤꯇꯩ ꯃꯌꯦꯛ) ꯈꯨꯔꯨꯝꯖꯔꯤ
Mende Kikakui (𞠀𞠁𞠂) 𞠛𞠉 Mende Kikakui (𞠀𞠁𞠂) 𞠛𞠉
Modi (𑘦𑘻𑘚𑘲) 𑘡𑘦𑘭𑘿𑘎𑘰𑘨 Modi (𑘦𑘻𑘚𑘲) 𑘡𑘦𑘭𑘿𑘎𑘰𑘨
Mongolian Cyrillic (монгол хэл) Сайн байна уу? Mongolian (монгол хэл) Сайн байна уу?
Mongolian Traditional (ᠮᠣᠩᠭᠣᠯ ᠪᠢᠴᠢᠭ᠋) ᠰᠠᠶᠢᠨ ᠪᠠᠶᠢᠨ᠎ᠠ ᠤᠤ?
Northern Thai (ᨣᩣᩴᨾᩮᩬᩥᨦ / ᨽᩣᩈᩣᩃ᩶ᩣ᩠ᨶᨶᩣ) ᩈ᩠ᩅᩢᩔ᩠ᨯᩦᨣᩕᩢ᩠ᨸ Northern Thai (ᨣᩣᩴᨾᩮᩬᩥᨦ / ᨽᩣᩈᩣᩃ᩶ᩣ᩠ᨶᨶᩣ) ᩈ᩠ᩅᩢᩔ᩠ᨯᩦᨣᩕᩢ᩠ᨸ
Norwegian (norsk) Hei / God dag Norwegian (norsk) Hei / God dag
Odia (ଓଡ଼ିଆ) ନମସ୍କାର Odia (ଓଡ଼ିଆ) ନମସ୍କାର

133
etc/NEWS
View file

@ -30,11 +30,6 @@ applies, and please also update docstrings as needed.
* Changes in Emacs 30.1 * Changes in Emacs 30.1
---
** New user option 'describe-bindings-outline-rules'.
This user option controls outline visibility in the output buffer of
'describe-bindings' when 'describe-bindings-outline' in non-nil.
** X selection requests are now handled much faster and asynchronously. ** X selection requests are now handled much faster and asynchronously.
This means it should be less necessary to disable the likes of This means it should be less necessary to disable the likes of
'select-active-regions' when Emacs is running over a slow network 'select-active-regions' when Emacs is running over a slow network
@ -71,11 +66,6 @@ This allows the user to customize the prompt that is appended by
This is used for displaying the time and date components of This is used for displaying the time and date components of
'display-time-mode'. 'display-time-mode'.
---
** New icon images for general use.
Several symbolic icons are added to "etc/images/symbols", including
plus, minus, check-mark, start, etc.
* Editing Changes in Emacs 30.1 * Editing Changes in Emacs 30.1
@ -110,7 +100,7 @@ If you want to get back the old behavior, set the user option to the value
(setopt gdb-locals-table-row-config (setopt gdb-locals-table-row-config
`((type . 0) (name . 0) (value . ,gdb-locals-value-limit))) `((type . 0) (name . 0) (value . ,gdb-locals-value-limit)))
** Grep ** Compile
*** New user option 'grep-use-headings'. *** New user option 'grep-use-headings'.
When non-nil, the output of Grep is split into sections, one for each When non-nil, the output of Grep is split into sections, one for each
@ -184,16 +174,11 @@ correctly unloads Eshell and all of its modules.
After manually editing 'eshell-aliases-file', you can use this command After manually editing 'eshell-aliases-file', you can use this command
to load the edited aliases. to load the edited aliases.
+++
*** 'rgrep' is now a builtin command.
Running 'rgrep' in Eshell now uses the Emacs grep facility instead of
calling external rgrep.
** Shell Mode ** Shell Mode
+++ +++
*** New user option 'shell-get-old-input-include-continuation-lines'. *** New user option 'shell-get-old-input-include-continuation-lines'.
When this user option is non-nil, 'shell-get-old-input' ('C-RET') When this user option is non-nil, 'shell-get-old-input' (C-RET)
includes multiple shell "\" continuation lines from command output. includes multiple shell "\" continuation lines from command output.
Default is nil. Default is nil.
@ -209,23 +194,16 @@ point is not in a comment or a string. It is by default bound to
** Tramp ** Tramp
+++ +++
*** New connection methods "toolbox" and "flatpak". *** New connection method "toolbox".
They allow accessing system containers provided by Toolbox or This allows accessing system containers provided by Toolbox.
sandboxes provided by Flatpak.
+++ +++
*** Rename 'tramp-use-ssh-controlmaster-options' to 'tramp-use-connection-share'. *** Rename 'tramp-use-ssh-controlmaster-options' to 'tramp-use-connection-share.
The old name still exists as obsolete variable alias. This user The old name still exists as defvaralias. This user option controls
option controls now connection sharing for both ssh-based and now connection sharing for both ssh-based and plink-based methods. It
plink-based methods. It allows the values t, nil, and 'suppress'. allows the values t, nil, and 'suppress'. The latter suppresses
The latter suppresses also "ControlMaster" settings in the user's also "ControlMaster" settings in the user's "~/.ssh/config" file,
"~/.ssh/config" file, or connection share configuration in PuTTY or connection share configuration in PuTTY sessions, respectively.
sessions, respectively.
+++
*** New command 'tramp-cleanup-some-buffers'.
It allows to kill only selected remote buffers, controlled by user
option 'tramp-cleanup-some-buffers-hook'.
** EWW ** EWW
@ -236,17 +214,6 @@ the new argument NEW-BUFFER non-nil, it will use a new buffer instead.
Interactively, invoke 'eww-open-file' with a prefix argument to Interactively, invoke 'eww-open-file' with a prefix argument to
activate this behavior. activate this behavior.
---
*** 'eww' URL or keyword prompt now has tab completion.
The interactive minibuffer prompt when invoking 'eww' now has support
for tab completion.
+++
*** 'eww' URL and keyword prompt now completes suggested URIs and bookmarks.
The interactive minibuffer prompt when invoking 'eww' now provides
completions from 'eww-suggest-uris'. 'eww-suggest-uris' now includes
bookmark URIs.
** go-ts-mode ** go-ts-mode
+++ +++
@ -294,34 +261,6 @@ When non-nil, it will automatically register every package as a
project, that you can quickly select using 'project-switch-project' project, that you can quickly select using 'project-switch-project'
('C-x p p'). ('C-x p p').
** Flymake
+++
*** New user option 'flymake-show-diagnostics-at-end-of-line'.
When non-nil, Flymake shows summarized descriptions of diagnostics at
the end of the line. Depending on your preference, this can either be
distracting and easily confused with actual code, or a significant
early aid that relieves you from moving the buffer or reaching for the
mouse to consult an error message.
** Python Mode
---
*** New user option 'python-indent-block-paren-deeper'.
If non-nil, increase the indentation of the lines inside parens in a
header of a block when they are indented to the same level as the body
of the block:
if (some_expression
and another_expression):
do_something()
instead of:
if (some_expression
and another_expression):
do_something()
* New Modes and Packages in Emacs 30.1 * New Modes and Packages in Emacs 30.1
@ -380,7 +319,7 @@ hooks named after the feature name, like 'esh-mode-unload-hook'.
* Lisp Changes in Emacs 30.1 * Lisp Changes in Emacs 30.1
** New variable 'inhibit-auto-fill' to temporarily prevent auto-fill. ** New var 'inhibit-auto-fill' to temporarily prevent auto-fill.
** Functions and variables to transpose sexps ** Functions and variables to transpose sexps
@ -496,7 +435,7 @@ any unwind forms, as in
(unwind-protect (read buffer)) (unwind-protect (read buffer))
because the behavior is identical to that of the argument; there is because the behaviour is identical to that of the argument; there is
no protection of any kind. Perhaps the intended unwind forms have no protection of any kind. Perhaps the intended unwind forms have
been misplaced or forgotten, or the use of 'unwind-protect' could be been misplaced or forgotten, or the use of 'unwind-protect' could be
simplified away. simplified away.
@ -504,50 +443,26 @@ simplified away.
This warning can be suppressed using 'with-suppressed-warnings' with This warning can be suppressed using 'with-suppressed-warnings' with
the warning name 'suspicious'. the warning name 'suspicious'.
--- +++
*** Warn about more ignored function return values. ** New function 'file-user-uid'.
The compiler now warns when the return value from certain functions is This function is like 'user-uid', but is aware of file name handlers,
implicitly ignored. Example: so it will return the remote UID for remote files (or -1 if the
connection has no associated user).
(progn (nreverse my-list) my-list)
will elicit a warning because it is usually pointless to call
'nreverse' on a list without using the returned value.
To silence the warning, make use of the value in some way, such as
assigning it to a variable. You can also wrap the function call in
'(ignore ...)', or use 'with-suppressed-warnings' with the warning
name 'ignored-return-value'.
The warning will only be issued for calls to functions declared
'important-return-value' or 'side-effect-free' (but not 'error-free').
+++ +++
** New function declaration and property 'important-return-value'. ** 'fset' and 'defalias' now signal an error for circular alias chains.
The declaration '(important-return-value t)' sets the Previously, 'fset' and 'defalias' could be made to build circular
'important-return-value' property which indicates that the function function indirection chains as in
return value should probably not be thrown away implicitly.
+++
** New functions 'file-user-uid' and 'file-group-gid'.
These functions are like 'user-uid' and 'group-gid', respectively, but
are aware of file name handlers, so they will return the remote UID or
GID for remote files (or -1 if the connection has no associated user).
+++
** 'fset', 'defalias' and 'defvaralias' now signal an error for cyclic aliases.
Previously, 'fset', 'defalias' and 'defvaralias' could be made to
build circular function and variable indirection chains as in
(defalias 'able 'baker) (defalias 'able 'baker)
(defalias 'baker 'able) (defalias 'baker 'able)
but trying to use them would sometimes make Emacs hang. Now, an attempt but trying to call them would often make Emacs hang. Now, an attempt
to create such a loop results in an error. to create such a loop results in an error.
Since circular alias chains now cannot occur, 'function-alias-p', Since circular alias chains now cannot occur, 'function-alias-p' and
'indirect-function' and 'indirect-variable' will never signal an error. 'indirect-function' will never signal an error. Their second
Their 'noerror' arguments have no effect and are therefore obsolete. 'noerror' arguments have no effect and are therefore obsolete.
* Changes in Emacs 30.1 on Non-Free Operating Systems * Changes in Emacs 30.1 on Non-Free Operating Systems

View file

@ -218,13 +218,13 @@ of 'user-emacs-directory'.
+++ +++
** The image commands have changed key bindings. ** The image commands have changed key bindings.
In previous Emacs versions, the '+', '-' and 'r' keys were bound when In previous Emacs versions, images have had the '+', '-' and 'r' keys
point was over an image. In Emacs 29.1, additional commands have been bound when point is over an image. In Emacs 29.1, additional commands
added, and this made it more likely that users would trigger the image were added, and this made it more likely that users would trigger the
commands by mistake. To avoid this, all image commands have been image commands by mistake. To avoid this, all image commands have
moved to the 'i' prefix keymap, so '+' is now 'i +', '-' is now 'i -', moved to the 'i' keymap, so '+' is now 'i +', '-' is now 'i -', and
and 'r' is now 'i r'. In addition, these commands are now repeating, 'r' is now 'i r'. In addition, these commands are now repeating, so
so you can rotate an image twice by saying 'i r r', for instance. you can rotate an image twice by saying 'i r r', for instance.
+++ +++
** Emacs now picks the correct coding-system for X input methods. ** Emacs now picks the correct coding-system for X input methods.
@ -380,7 +380,7 @@ this user option to nil to revert back to the old behavior.
--- ---
** Support for old EIEIO functions is not autoloaded any more. ** Support for old EIEIO functions is not autoloaded any more.
You need an explicit '(require 'eieio-compat)' to use 'defmethod' You need an explicit '(require 'eieio-compat)' to use 'defmethod'
and 'defgeneric' (which were made obsolete in Emacs 25.1 by and 'defgeneric' (which have been made obsolete in Emacs 25.1 with
'cl-defmethod' and 'cl-defgeneric'). 'cl-defmethod' and 'cl-defgeneric').
Similarly you might need to '(require 'eieio-compat)' before loading Similarly you might need to '(require 'eieio-compat)' before loading
files that were compiled with an old EIEIO (Emacs<25). files that were compiled with an old EIEIO (Emacs<25).
@ -497,7 +497,7 @@ the 'nlinum' package from GNU ELPA instead. The former has better
performance, but the latter is closer to a drop-in replacement. performance, but the latter is closer to a drop-in replacement.
1. To use 'display-line-numbers-mode', add something like this to your 1. To use 'display-line-numbers-mode', add something like this to your
init file: Init file:
(global-display-line-numbers-mode 1) (global-display-line-numbers-mode 1)
;; Alternatively, to use it only in programming modes: ;; Alternatively, to use it only in programming modes:
@ -517,7 +517,7 @@ performance, but the latter is closer to a drop-in replacement.
--- ---
** The thumbs.el library is now obsolete. ** The thumbs.el library is now obsolete.
We recommend using the 'image-dired' command instead. We recommend using command 'image-dired' instead.
--- ---
** The autoarg.el library is now marked obsolete. ** The autoarg.el library is now marked obsolete.
@ -577,7 +577,7 @@ encoding, only for decoding.
** New user option 'major-mode-remap-alist' to specify favorite major modes. ** New user option 'major-mode-remap-alist' to specify favorite major modes.
This user option lets you remap the default modes (e.g. 'perl-mode' or This user option lets you remap the default modes (e.g. 'perl-mode' or
'latex-mode') to your favorite ones (e.g. 'cperl-mode' or 'latex-mode') to your favorite ones (e.g. 'cperl-mode' or
'LaTeX-mode') instead of having to use 'defalias', which can have 'LaTeX-mode') without having to use 'defalias', which can have
undesirable side effects. undesirable side effects.
This applies to all modes specified via 'auto-mode-alist', file-local This applies to all modes specified via 'auto-mode-alist', file-local
variables, etc. variables, etc.
@ -587,8 +587,6 @@ variables, etc.
--- ---
** New user option 'electric-quote-replace-consecutive'. ** New user option 'electric-quote-replace-consecutive'.
This allows you to disable the default behavior of consecutive single
quotes being replaced with a double quote.
--- ---
** Emacs is now capable of editing files with very long lines. ** Emacs is now capable of editing files with very long lines.
@ -797,14 +795,13 @@ part of the buffer.
+++ +++
** New user option 'set-message-functions'. ** New user option 'set-message-functions'.
It allows more flexible control of how echo-area messages are displayed It allows selecting more functions for 'set-message-function'
by adding functions to this list. The default value is a list of one in addition to the default function that handles messages
element: 'set-minibuffer-message', which displays echo-area messages in the active minibuffer. The most useful are 'inhibit-message'
at the end of the minibuffer text when the minibuffer is active. that allows specifying a list of messages to inhibit via
Other useful functions include 'inhibit-message', which allows 'inhibit-message-regexps', and 'set-multi-message' that
specifying, via 'inhibit-message-regexps', the list of messages whose accumulates recent messages and displays them stacked
display should be inhibited; and 'set-multi-message' that accumulates in the echo area.
recent messages and displays them stacked together.
--- ---
** New user option 'find-library-include-other-files'. ** New user option 'find-library-include-other-files'.
@ -857,17 +854,17 @@ This value stands for the value of the corresponding attribute of the
inheriting from other faces. inheriting from other faces.
+++ +++
** New X resource "borderThickness". ** New X resource: "borderThickness".
This controls the thickness of the external borders of the menu bars This controls the thickness of the external borders of the menu bars
and pop-up menus. and pop-up menus.
+++ +++
** New X resource "inputStyle". ** New X resource: "inputStyle".
This controls the style of the pre-edit and status areas of X input This controls the style of the pre-edit and status areas of X input
methods. methods.
+++ +++
** New X resources "highlightForeground" and "highlightBackground". ** New X resources: "highlightForeground" and "highlightBackground".
Only in the Lucid build, this controls colors used for highlighted Only in the Lucid build, this controls colors used for highlighted
menu item widgets. menu item widgets.
@ -904,7 +901,7 @@ frame's contents will be hidden, leaving only the title bar on display.
--- ---
** New user option 'x-gtk-use-native-input'. ** New user option 'x-gtk-use-native-input'.
This controls whether or not GTK input methods are used by Emacs, This controls whether or not GTK input methods are used by Emacs,
instead of XIM input methods. Defaults to nil. instead of XIM input methods.
+++ +++
** New user option 'use-system-tooltips'. ** New user option 'use-system-tooltips'.
@ -1001,17 +998,17 @@ combinations in a graphical menu system.
+++ +++
*** New command 'emoji-search' (bound to 'C-x 8 e s'). *** New command 'emoji-search' (bound to 'C-x 8 e s').
This command lets you search for and insert an Emoji based on names. This command lets you search for Emoji based on names.
+++ +++
*** New command 'emoji-list' (bound to 'C-x 8 e l'). *** New command 'emoji-list' (bound to 'C-x 8 e l').
This command lists all Emoji (categorized by themes) in a special This command lists all Emoji (categorized by themes) in a special
buffer and lets you choose one of them to insert. buffer and lets you choose one of them.
--- ---
*** New command 'emoji-recent' (bound to 'C-x 8 e r'). *** New command 'emoji-recent' (bound to 'C-x 8 e r').
This command lets you choose among the Emoji you have recently This command lets you choose among the Emoji you have recently
inserted and insert it. inserted.
+++ +++
*** New command 'emoji-describe' (bound to 'C-x 8 e d'). *** New command 'emoji-describe' (bound to 'C-x 8 e d').
@ -1023,11 +1020,6 @@ works for non-Emoji characters.)
These are bound to 'C-x 8 e +' and 'C-x 8 e -', respectively. They These are bound to 'C-x 8 e +' and 'C-x 8 e -', respectively. They
can be used on any character, but are mainly useful for Emoji. can be used on any character, but are mainly useful for Emoji.
---
*** New command 'emoji-zoom-reset'.
This is bound to 'C-x 8 e 0', and undoes any size changes performed by
'emoji-zoom-increase' and 'emoji-zoom-decrease'.
--- ---
*** New input method 'emoji'. *** New input method 'emoji'.
This allows you to enter Emoji using short strings, eg ':face_palm:' This allows you to enter Emoji using short strings, eg ':face_palm:'
@ -1045,7 +1037,7 @@ quotes removed.
--- ---
*** 'M-x apropos-variable' output now includes values of variables. *** 'M-x apropos-variable' output now includes values of variables.
Such an apropos buffer is more easily viewed with outlining after Such apropos buffer is more easily viewed with outlining after
enabling 'outline-minor-mode' in 'apropos-mode'. enabling 'outline-minor-mode' in 'apropos-mode'.
+++ +++
@ -1077,7 +1069,7 @@ This has been changed to:
+++ +++
*** The 'C-h .' command now accepts a prefix argument. *** The 'C-h .' command now accepts a prefix argument.
'C-u C-h .' would previously inhibit displaying a warning message if 'C-u C-h .' would previously inhibit displaying a warning message if
there was no local help at point. This has been changed to call there's no local help at point. This has been changed to call
'button-describe'/'widget-describe' and display button/widget help 'button-describe'/'widget-describe' and display button/widget help
instead. instead.
@ -1130,7 +1122,7 @@ helpful commands for various tasks. You can toggle the display using
'C-h C-q'. 'C-h C-q'.
** Emacs now comes with Org v9.6. ** Emacs now comes with Org v9.6.
See the file "etc/ORG-NEWS" for user-visible changes in Org. See the file "ORG-NEWS" for user-visible changes in Org.
** Outline Mode ** Outline Mode
@ -1193,13 +1185,12 @@ the display of several buffers in a row more amenable.
+++ +++
*** New buffer display action alist entry 'lru-frames'. *** New buffer display action alist entry 'lru-frames'.
This allows specifying which frames 'display-buffer' should consider This allows to specify which frames 'display-buffer' should consider
when using a window that shows another buffer. It is interpreted as when using a window that shows another buffer.
per the ALL-FRAMES argument of 'get-lru-window'.
+++ +++
*** New buffer display action alist entry 'lru-time'. *** New buffer display action alist entry 'lru-time'.
'display-buffer' will ignore windows with a use time higher than this 'display-buffer' will ignore windows with a use time higher than that
when using a window that shows another buffer. when using a window that shows another buffer.
+++ +++
@ -1209,14 +1200,12 @@ making it a less likely candidate for displaying another buffer.
+++ +++
*** New buffer display action alist entry 'window-min-width'. *** New buffer display action alist entry 'window-min-width'.
This allows specifying a preferred minimum width of the window used to This allows to specify a minimum width of the window used to display a
display a buffer. buffer.
--- ---
*** You can specify on which window 'scroll-other-window' operates. *** You can customize on which window 'scroll-other-window' operates.
This is controlled by the new 'other-window-scroll-default' variable, This is controlled by the new 'other-window-scroll-default' variable.
which should be set to a function that returns a window. When this
variable is nil, 'next-window' is used.
** Frames ** Frames
@ -1279,19 +1268,17 @@ respond within N seconds. The default is to wait forever.
+++ +++
*** 'server-stop-automatically' can be used to automatically stop the server. *** 'server-stop-automatically' can be used to automatically stop the server.
The Emacs server will be automatically stopped when certain conditions The Emacs server will be automatically stopped when certain conditions
are met. The conditions are determined by the argument to are met. The conditions are given by the argument, which can be
'server-stop-automatically', which can be 'empty', 'delete-frame' or 'empty', 'delete-frame' or 'kill-terminal'.
'kill-terminal'.
** Rcirc ** Rcirc
+++ +++
*** New command 'rcirc-when'. *** New command 'rcirc-when'.
This shows the reception time of the message at point (if available).
+++ +++
*** New user option 'rcirc-cycle-completion-flag'. *** New user option 'rcirc-cycle-completion-flag'.
Rcirc now uses the default 'completion-at-point' mechanism. The Rcirc will use the default 'completion-at-point' mechanism. The
conventional IRC behavior of completing by cycling through the conventional IRC behavior of completing by cycling through the
available options can be restored by enabling this option. available options can be restored by enabling this option.
@ -1546,10 +1533,6 @@ environments are:
Coptic script and language environment Coptic script and language environment
Mongolian-traditional script and language environment
Mongolian-cyrillic language environment
--- ---
*** The "Oriya" language environment was renamed to "Odia". *** The "Oriya" language environment was renamed to "Odia".
This is to follow the change in the official name of the script. The This is to follow the change in the official name of the script. The
@ -1563,10 +1546,7 @@ Type 'C-u C-h t' to select it in case your language setup does not do
so automatically. so automatically.
--- ---
*** New Ukrainian translation of the Emacs tutorial. *** New Ukrainian translation of the Emacs Tutorial.
---
*** New Farsi/Persian translation of the Emacs tutorial.
--- ---
*** New default phonetic input method for the Tamil language environment. *** New default phonetic input method for the Tamil language environment.
@ -1591,12 +1571,6 @@ This input method is based on the russian-computer input method, and
is intended for typing in the Chuvash language written in the Cyrillic is intended for typing in the Chuvash language written in the Cyrillic
script. script.
---
*** New input method 'cyrillic-mongolian'.
This input method is for typing in the Mongolian language using the
Cyrillic script. It is the default input method for the new
Mongolian-cyrillic language environment, see above.
* Changes in Specialized Modes and Packages in Emacs 29.1 * Changes in Specialized Modes and Packages in Emacs 29.1
@ -1843,18 +1817,13 @@ this includes "binary" buffers like 'archive-mode' and 'image-mode'.
** Package ** Package
+++ +++
*** New command 'package-upgrade'. *** New command 'package-update'.
This command allows you to upgrade packages without using 'M-x This command allows you to upgrade packages without using 'M-x
list-packages'. A package that comes with the Emacs distribution can list-packages'.
only be upgraded after you install, once, a newer version from ELPA
via the package-menu displayed by 'list-packages'.
+++ +++
*** New command 'package-upgrade-all'. *** New command 'package-update-all'.
This command allows upgrading all packages without any queries. This command allows updating all packages without any queries.
A package that comes with the Emacs distribution will only be upgraded
by this command after you install, once, a newer version of that
package from ELPA via the package-menu displayed by 'list-packages'.
+++ +++
*** New commands 'package-recompile' and 'package-recompile-all'. *** New commands 'package-recompile' and 'package-recompile-all'.
@ -1889,26 +1858,13 @@ packages checked out using 'package-vc-install'.
+++ +++
*** New command 'package-report-bug'. *** New command 'package-report-bug'.
This command helps you compose an email for sending bug reports to This command helps you compose an email for sending bug reports to
package maintainers, and is bound to 'b' in the "*Packages*" buffer. package maintainers.
+++ +++
*** New user option 'package-vc-selected-packages'. *** New user option 'package-vc-selected-packages'.
By customizing this user option you can specify specific packages to By customizing this user option you can specify specific packages to
install. install.
---
*** New user option 'package-install-upgrade-built-in'.
When enabled, 'package-install' will include in the list of
upgradeable packages those built-in packages (like Eglot and
use-package, for example) for which a newer version is available in
package archives, and will allow installing those newer versions. By
default, this is disabled; however, if 'package-install' is invoked
with a prefix argument, it will act as if this new option were
enabled.
If you customize this option, we recommend you place its non-default
setting in your early-init file.
** Emacs Sessions (Desktop) ** Emacs Sessions (Desktop)
+++ +++
@ -1966,8 +1922,8 @@ displayed in a window.
+++ +++
*** New user option 'compilation-hidden-output'. *** New user option 'compilation-hidden-output'.
This regular expression can be used to make specific parts of This can be used to make specific parts of compilation output
compilation output invisible. invisible.
+++ +++
*** The 'compilation-auto-jump-to-first-error' user option has been extended. *** The 'compilation-auto-jump-to-first-error' user option has been extended.
@ -2350,7 +2306,7 @@ EUDC inline expansion result formatting defaulted to
("%s %s <%s>" firstname name email) ("%s %s <%s>" firstname name email)
Since email address specifications need to comply with RFC 5322 in Since email address specifications need to comply with RFC 5322 in
order to be useful in messages, there was a risk of producing syntax order to be useful in messages, there was a risk to produce syntax
which was standard with RFC 822, but is marked as obsolete syntax by which was standard with RFC 822, but is marked as obsolete syntax by
its successor RFC 5322. Also, the first and last name part was never its successor RFC 5322. Also, the first and last name part was never
enclosed in double quotes, potentially producing invalid address enclosed in double quotes, potentially producing invalid address
@ -2384,8 +2340,8 @@ used to select the entry type in the ecomplete database.
+++ +++
*** New back-end for mailabbrev. *** New back-end for mailabbrev.
A new back-end for mailabbrev allows information from that database to A new back-end for mailabbrev allows information from that database to
be queried by EUDC, too. Only the attributes 'email', 'name', and be queried by EUDC, too. The attributes 'email', 'name', and 'firstname'
'firstname' are supported. are supported only.
** EWW/SHR ** EWW/SHR
@ -2632,14 +2588,14 @@ as opposed to via the command-line.
+++ +++
*** New command 'image-transform-fit-to-window'. *** New command 'image-transform-fit-to-window'.
This command fits the image to the current window by scaling down or This command fits the image to the current window by scaling down or
up as necessary. Unlike 'image-transform-fit-both', this can scale up as necessary. Unlike 'image-transform-fit-both', this does not
the image up as well as down. It is bound to 's w' in Image Mode by only scale the image down, but up as well. It is bound to 's w' in
default. Image Mode by default.
--- ---
*** New command 'image-mode-wallpaper-set'. *** New command 'image-mode-wallpaper-set'.
This command sets the desktop background to the current image. It is This command sets the desktop background to the current image. It is
bound to 'W' in Image Mode by default. bound to 'W' by default.
+++ +++
*** 'image-transform-fit-to-{height,width}' are now obsolete. *** 'image-transform-fit-to-{height,width}' are now obsolete.
@ -2657,14 +2613,19 @@ much (in percent). It is nil by default, which means no limit.
--- ---
*** New user option 'image-text-based-formats'. *** New user option 'image-text-based-formats'.
This controls whether or not to show a message, when opening certain This controls whether or not to show a message when opening certain
image formats, explaining how to edit it as text. The default is to image formats saying how to edit it as text. The default is to show
show this message for SVG and XPM. this message for SVG and XPM.
+++
*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'.
These commands horizontally and vertically flip the image under point,
and are bound to 'i h' and 'i v', respectively.
+++ +++
*** New command 'image-transform-set-percent'. *** New command 'image-transform-set-percent'.
It allows resizing the image to a percentage of its original size, and It allows setting the image size to a percentage of its original size,
is bound to 's p' in Image mode. and is bound to 's p' in Image mode.
+++ +++
*** 'image-transform-original' renamed to 'image-transform-reset-to-original'. *** 'image-transform-original' renamed to 'image-transform-reset-to-original'.
@ -2676,19 +2637,6 @@ The old name was confusing, and is now an obsolete function alias.
** Images ** Images
+++
*** New commands 'image-crop' and 'image-cut'.
These commands allow interactively cropping/cutting the image at
point. The commands are bound to keys 'i c' and 'i x' (respectively)
in the local keymap over images. They rely on external programs, by
default "convert" from ImageMagick, to do the actual cropping/eliding
of the image file.
+++
*** New commands 'image-flip-horizontally' and 'image-flip-vertically'.
These commands horizontally and vertically flip the image under point,
and are bound to 'i h' and 'i v', respectively.
+++ +++
*** Users can now add special image conversion functions. *** Users can now add special image conversion functions.
This is done via 'image-converter-add-handler'. This is done via 'image-converter-add-handler'.
@ -3277,10 +3225,6 @@ based on data provided by language servers using the Language Server
Protocol (LSP). See the new Info manual "(eglot) Top" for more. Also Protocol (LSP). See the new Info manual "(eglot) Top" for more. Also
see "etc/EGLOT-NEWS". see "etc/EGLOT-NEWS".
If you want to be able to use 'package-install' to upgrade Eglot to
newer versions released on GNU ELPA, customize the new option
'package-install-upgrade-built-in' to a non-nil value.
+++ +++
** use-package: Declarative package configuration. ** use-package: Declarative package configuration.
use-package is now shipped with Emacs. It provides the 'use-package' use-package is now shipped with Emacs. It provides the 'use-package'
@ -3288,9 +3232,13 @@ macro, which allows you to isolate package configuration in your init
file in a way that is declarative, tidy, and performance-oriented. file in a way that is declarative, tidy, and performance-oriented.
See the new Info manual "(use-package) Top" for more. See the new Info manual "(use-package) Top" for more.
If you want to be able to use 'package-install' to upgrade use-package +++
to newer versions released on GNU ELPA, customize the new option ** New commands 'image-crop' and 'image-cut'.
'package-install-upgrade-built-in' to a non-nil value. These commands allow interactively cropping/cutting the image at
point. The commands are bound to keys 'i c' and 'i x' (respectively)
in the local keymap over images. They rely on external programs, by
default "convert" from ImageMagick, to do the actual cropping/eliding
of the image file.
--- ---
** New package 'wallpaper'. ** New package 'wallpaper'.
@ -3956,9 +3904,9 @@ connection-local profile.
+++ +++
*** New macro 'with-connection-local-application-variables'. *** New macro 'with-connection-local-application-variables'.
This macro works like 'with-connection-local-variables', but it allows This macro works like 'with-connection-local-variables', but it allows
using another application instead of 'tramp'. This is useful when to use another application but 'tramp'. This is useful when running
running code in a buffer where Tramp has already set some code in a buffer where Tramp has already set some connection-local
connection-local variables. variables.
+++ +++
*** New macro 'setq-connection-local'. *** New macro 'setq-connection-local'.
@ -4037,8 +3985,8 @@ This returns a list of sub-sequences of the specified sequence.
+++ +++
*** New function 'seq-remove-at-position'. *** New function 'seq-remove-at-position'.
This function returns a copy of the specified sequence with the This function returns a copy of the specified sequence where the
element at a given (zero-based) index removed. element at a given (zero-based) index got removed.
+++ +++
*** New function 'seq-positions'. *** New function 'seq-positions'.
@ -4106,7 +4054,7 @@ that quote character has to be escaped to avoid Emacs displaying it as
(setq foo '(1 2 3)) (setq foo '(1 2 3))
invalid. Emacs will now warn during byte compilation if it sees invalid. Emacs will now warn during byte compilation if it seems
something like that, and also warn about when using RIGHT/LEFT SINGLE something like that, and also warn about when using RIGHT/LEFT SINGLE
QUOTATION MARK directly. In both these cases, if these characters QUOTATION MARK directly. In both these cases, if these characters
should really be present in the docstring, they should be quoted with should really be present in the docstring, they should be quoted with
@ -4166,7 +4114,7 @@ example for benchmarking purposes.
** New function 'string-edit'. ** New function 'string-edit'.
This is meant to be used when the user has to edit a (potentially) This is meant to be used when the user has to edit a (potentially)
long string. It pops up a new buffer where you can edit the string, long string. It pops up a new buffer where you can edit the string,
and the provided callback is called when the user types 'C-c C-c'. and a callback is called when the user types 'C-c C-c'.
+++ +++
** New function 'read-string-from-buffer'. ** New function 'read-string-from-buffer'.
@ -4312,7 +4260,7 @@ them towards or away from each other.
+++ +++
** New hook 'x-pre-popup-menu-hook'. ** New hook 'x-pre-popup-menu-hook'.
This hook is run before 'x-popup-menu' is about to display a This hook, run before 'x-popup-menu', is about to display a
deck-of-cards menu on screen. deck-of-cards menu on screen.
--- ---
@ -4374,11 +4322,9 @@ that binding is ignored by 'where-is-internal'.
+++ +++
*** New functions for defining and manipulating keystrokes. *** New functions for defining and manipulating keystrokes.
These all take the syntax defined by 'key-valid-p', which is basically These all take the syntax defined by 'key-valid-p'. None of the older
the same syntax as the one accepted by the 'kbd' macro. None of the functions have been deprecated or altered, but they are now
older functions have been deprecated or altered, but they are now de-emphasized in the documentation.
de-emphasized in the documentation, and we encourage Lisp programs to
switch to these new functions.
+++ +++
*** Use 'keymap-set' instead of 'define-key'. *** Use 'keymap-set' instead of 'define-key'.
@ -4413,8 +4359,8 @@ switch to these new functions.
+++ +++
*** 'define-key' now takes an optional REMOVE argument. *** 'define-key' now takes an optional REMOVE argument.
If non-nil, remove the definition from the keymap. This is subtly If non-nil, remove the definition from the keymap. This is subtly
different from setting a definition to nil: when the keymap has a different from setting a definition to nil (when the keymap has a
parent such a definition will shadow the parent's definition. parent).
+++ +++
*** 'read-multiple-choice' now takes an optional SHOW-HELP argument. *** 'read-multiple-choice' now takes an optional SHOW-HELP argument.

View file

@ -2708,15 +2708,6 @@ Emacs so that it isn't compiled with '-O5'.
We list bugs in current versions here. See also the section on legacy We list bugs in current versions here. See also the section on legacy
systems. systems.
*** On Solaris 10, running 'configure' with "/bin/sh" produces errors.
The "/bin/sh" shell on Solaris is an ancient and non-POSIX shell, so
we recommend not to use it. The Emacs 'configure' script should find
an appropriate shell and re-exec itself with that shell, unless you
force it to use "/bin/sh" by using "CONFIG_SHELL=/bin/sh" on the
'configure' command line. So either don't use CONFIG_SHELL, or, if
you'd rather pick the shell yourself, choose "/bin/bash" or "/bin/ksh"
or "/usr/xpg4/bin/sh" instead.
*** On Solaris 10 sparc, Emacs crashes during the build while saving state. *** On Solaris 10 sparc, Emacs crashes during the build while saving state.
This was observed for Emacs 28.1 on Solaris 10 32-bit sparc, with This was observed for Emacs 28.1 on Solaris 10 32-bit sparc, with
Oracle Developer Studio 12.6 (Sun C 5.15). The failure was intermittent, Oracle Developer Studio 12.6 (Sun C 5.15). The failure was intermittent,

View file

@ -1,5 +1,5 @@
% Reference Card for Org Mode % Reference Card for Org Mode
\def\orgversionnumber{9.6.5} \def\orgversionnumber{9.6.2}
\def\versionyear{2023} % latest update \def\versionyear{2023} % latest update
\input emacsver.tex \input emacsver.tex

View file

@ -4,7 +4,7 @@ Emacs commands generally involve the CONTROL key (often labeled CTRL)
or the META key (usually labeled ALT). Rather than writing that or the META key (usually labeled ALT). Rather than writing that
in full each time, we'll use the following abbreviations: in full each time, we'll use the following abbreviations:
C-<chr> means hold the CONTROL key while typing the character <chr>. C-<chr> means hold the CONTROL key while typing the character <chr>
Thus, C-f would be: hold the CONTROL key and type f. Thus, C-f would be: hold the CONTROL key and type f.
M-<chr> means hold the META or ALT key down while typing <chr>. M-<chr> means hold the META or ALT key down while typing <chr>.
If there is no META or ALT key, instead press and release the If there is no META or ALT key, instead press and release the

View file

@ -15,10 +15,10 @@ META 键(有时候用 EDIT 或 ALT 来标示)。为了避免每次都要写
ESC 键。 ESC 键。
重要提示:要退出 Emacs请用 C-x C-c两个连续的组合键 重要提示:要退出 Emacs请用 C-x C-c两个连续的组合键
中断一个正在输入的命令,请用 C-g。 退出一个正在运行中的命令,请用 C-g。
下文中左边顶行的“>>”字样用来提示你尝试键盘命令。比如: 下文中左边顶行的“>>”字样用来提示你尝试键盘命令。比如:
<<Blank lines inserted around following line by help-with-tutorial>> <<Blank lines inserted around following line by help-with-tutorial>>
【本页当中特意留出一些空白是出于教学目的,请继续往后阅读】 [本页当中特意留出一些空白是出于教学目的,请继续往后阅读]
>> 现在输入 C-v (查看下一屏文字)移动到下一屏。 >> 现在输入 C-v (查看下一屏文字)移动到下一屏。
(别紧张,在输入字符 v 的同时注意要按住 CONTROL 键) (别紧张,在输入字符 v 的同时注意要按住 CONTROL 键)
从现在开始,每读完当前一屏你都需要这样做一次。 从现在开始,每读完当前一屏你都需要这样做一次。
@ -26,17 +26,12 @@ META 键(有时候用 EDIT 或 ALT 来标示)。为了避免每次都要写
值得注意的是,当你从上一屏滚到下一屏时,中间会有两行的重复;这样做是为 值得注意的是,当你从上一屏滚到下一屏时,中间会有两行的重复;这样做是为
了维持滚屏的连续性,方便你顺畅、连续地阅读。 了维持滚屏的连续性,方便你顺畅、连续地阅读。
这是 Emacs 教程文本的一个经过少量修改的副本。不久后我们会让你尝试不同
的命令来修改此文本。若你在我们提到这些命令前修改了文本,不要担心;这就
叫做“编辑”,而这就是 Emacs 存在的根本原因。
用编辑器,开门第一件事就是学会在文字中移动。你已经知道了 C-v 可以向下移 用编辑器,开门第一件事就是学会在文字中移动。你已经知道了 C-v 可以向下移
动一屏,要往上移,请用 M-v (也就是按住 META 键然后输入v如果你没有 动一屏,要往上移,请用 M-v (也就是按住 META 键然后输入v如果你没有
META、EDIT 或 ALT 键那么就先按 <ESC> 再按 v META、EDIT 或 ALT 键那么就先按 <ESC> 再按 v
>> 试试 M-v然后再试试 C-v来回遛几次。 >> 试试 M-v然后再试试 C-v来回遛几次。
若你知道其他移动文本的方式,也可以在这里试试。
* 小结SUMMARY * 小结SUMMARY
----------------- -----------------
@ -106,7 +101,7 @@ P 代表 previous上一行N 代表 next下一行B 代表 backw
如果你嫌一个字符一个字符地挪光标太慢你还可以一个词一个词地跳。M-f 如果你嫌一个字符一个字符地挪光标太慢你还可以一个词一个词地跳。M-f
(META-f) 可以将光标往前移动一个词,而 M-b 则是往后移。【这里的“词”指 (META-f) 可以将光标往前移动一个词,而 M-b 则是往后移。【这里的“词”指
英文单词,对中文来说,则是指移动到下一个空格或标点符号。】 英文单词,对中文来说,则是指移动到下一个标点符号。】
>> 试试 M-f 和 M-b。 >> 试试 M-f 和 M-b。
@ -137,8 +132,8 @@ P 代表 previous上一行N 代表 next下一行B 代表 backw
C-f 向右移动一个字符 C-f 向右移动一个字符
C-b 向左移动一个字符 C-b 向左移动一个字符
M-f 向右移动一个词【对中文是移动到下一个空格或标点符号】 M-f 向右移动一个词【对中文是移动到下一个标点符号】
M-b 向左移动一个词【对中文是移动到上一个空格或标点符号】 M-b 向左移动一个词【对中文是移动到上一个标点符号】
C-n 移动到下一行 C-n 移动到下一行
C-p 移动到上一行 C-p 移动到上一行
@ -165,25 +160,24 @@ M-commaMETA 逗号)。
然后再按几次 M-v 回到这里。 然后再按几次 M-v 回到这里。
如果你的键盘上有方向键的话,也可以用它们来移动光标。不过我们有三个理由 如果你的键盘上有方向键的话,也可以用它们来移动光标。不过我们有三个理由
推荐你学习 C-b 、C-f 、C-n 、和 C-p1它们在任何终端terminal 推荐你学习 C-b 、C-f 、C-n 、和 C-p1它们在任何键盘上都能用。2
都能用。2当你熟练使用 Emacs 之后,你会发现用这些组合键比用方向键要 当你熟练使用 Emacs 之后,你会发现用这些组合键比用方向键要快得多,因为你
快得多,因为你的手不需要离开打字区。3一旦你习惯了使用这些组合键 的手不需要离开打字区。3一旦你习惯了使用这些组合键你也可以很容易地
你也可以很容易地适应其它更高级的光标移动命令。 适应其它更高级的光标移动命令。
大部分的 Emacs 命令接受数字参数,并且对于多数命令而言,这些数字参数的 大部分的 Emacs 命令接受数字参数,并且对于多数命令而言,这些数字参数的作
作用是指定命令的重复次数。为一个命令指定数字参数(也就是重复次数)的方 用是指定命令的重复次数。为一个命令指定数字参数(也就是重复次数)的方法
法是:先输入 C-u然后输入数字作为参数最后再输入命令。如果你有 是:先输入 C-u然后输入数字作为参数最后再输入命令。如果你有META (或
META或EDIT 或 ALT那么还有另一种办法按住 META 键不放,然后输 EDIT 或 ALT那么还有另一种办法按住 META 键不放,然后输入数字。不
入数字。不过我们还是建议你用 C-u因为它在任何终端上都能用。这种数字参 过我们还是建议你用 C-u因为它在任何终端机上都能用。这种数字参数也称为
数也称为“前缀参数”prefix argument意思是说这个参数是先于使用它的 “前缀参数”,意思是说这个参数是先于使用它的命令而输入的。
命令而输入的。
举例来说, C-u 8 C-f 会向前移动 8 个字符。 举例来说, C-u 8 C-f 会向前移动 8 个字符。
>> 为 C-n 或者 C-p 指定一个数字参数,这样你可以只用一个命令就把光标移动 >> 为 C-n 或者 C-p 指定一个数字参数,这样你可以只用一个命令就把光标移动
到本行的附近。 到本行的附近。
虽然大部分命令把数字参数解为其重复次数,但是也有些命令例外,它们将数 虽然大部分命令把数字参数解为其重复次数,但是也有些命令例外,它们将数
字参数另做它用。比如有些命令(我们目前还没学到)仅仅将前缀参数作为一个 字参数另做它用。比如有些命令(我们目前还没学到)仅仅将前缀参数作为一个
标志――只要给出有一个前缀参数,不管其值为何,它都会改变命令的功能。 标志――只要给出有一个前缀参数,不管其值为何,它都会改变命令的功能。
@ -195,7 +189,7 @@ META或EDIT 或 ALT那么还有另一种办法按住 META 键不
这个命令应该已经将文字向上滚动了 8 行。如果你想将它再次地向下滚动,你可 这个命令应该已经将文字向上滚动了 8 行。如果你想将它再次地向下滚动,你可
以给定一个参数然后执行 M-v。 以给定一个参数然后执行 M-v。
如果你正在使用图形界面,比如 X 或者微软的 Windows那么在 Emacs 如果你正在使用图形界面,比如 X 或者微软的 Windows那么在 Emacs窗
口的一边应该有一个长方形的区域叫“滚动条”。你可以用鼠标操纵滚动条来滚动 口的一边应该有一个长方形的区域叫“滚动条”。你可以用鼠标操纵滚动条来滚动
文字。 文字。
@ -241,8 +235,8 @@ Emacs 可以有多个“窗格”,每个窗格显示不同的文字。后面
C-x 1 只保留一个窗格(也就是关掉其它所有窗格)。 C-x 1 只保留一个窗格(也就是关掉其它所有窗格)。
也就是先按 CONTROL-x 然后再按数字 1。C-x 1 会保留光标所在的窗格,并将 也就是先按 CONTROL-x 然后再按 1。C-x 1 会保留光标所在的窗格,并将其扩大
其扩大到整个屏幕,同时关掉所有其它的窗格。 到整个屏幕,同时关掉所有其它的窗格。
>> 把光标移到本行然后输入 C-u 0 C-l。 >> 把光标移到本行然后输入 C-u 0 C-l。
@ -272,13 +266,12 @@ Emacs 可以有多个“窗格”,每个窗格显示不同的文字。后面
不用担心文件被修改,你做什么都没关系,这里就是专给你练习用的。 不用担心文件被修改,你做什么都没关系,这里就是专给你练习用的。
如果一行文字很长、超出了窗格的宽度,显示不下的部分会在紧邻的下一行继续 如果一行文字很长、超出了窗格的宽度,显示不下的部分会在紧邻的下一行继续
显示称为接续行continuation line。如果你使用的是图形界面文本区 显示。如果你使用的是图形界面,文本区域两边的狭窄区域(左右“边缘”)会出
域两边的狭窄区域(左右“边缘”)会出现小小的转弯箭头,表明这是某一行的接 现小小的转弯箭头,表明这是某一行的接续显示。如果你使用的是文本终端,接
续显示。如果你使用的是文本终端,接续显示由屏幕最右边一列的一个“\”来表 续显示由屏幕最右边一列的一个反斜线(“\”)来表示。
示。
>> 输入文字,一直到屏幕的右边界,然后继续。 >> 输入文字,一直到屏幕的右边界,然后继续。
你会看到一个接续行出现。 你会看到一个接续行出现。
>> 用 <DEL> 删掉一些文字,直到此行长度小于窗格宽度,接续行就消失了。 >> 用 <DEL> 删掉一些文字,直到此行长度小于窗格宽度,接续行就消失了。
@ -293,9 +286,7 @@ Emacs 可以有多个“窗格”,每个窗格显示不同的文字。后面
<Return> 是一个特殊的键,因为按下这个键后,得到的可能不仅仅是一个换行 <Return> 是一个特殊的键,因为按下这个键后,得到的可能不仅仅是一个换行
符。根据周围文本的不同Emacs 可能会在换行符之后插入一些空白字符,这样, 符。根据周围文本的不同Emacs 可能会在换行符之后插入一些空白字符,这样,
当你在新的一行开始打字时,文本会自动与前一行对齐。我们称这种行为(在按 当你在新的一行开始打字时,文本会自动与前一行对齐。
这个按键时不只是插入其对应字符为“electric”可以理解为“通电的自动
的”。
>> 这是一个自动缩进的例子。 >> 这是一个自动缩进的例子。
在这一行的末尾输入 <Return>。 在这一行的末尾输入 <Return>。
@ -347,8 +338,7 @@ Emacs 可以有多个“窗格”,每个窗格显示不同的文字。后面
了。】重新插入被移除的文字称为“召回yank”。一般而言那些可能消除很 了。】重新插入被移除的文字称为“召回yank”。一般而言那些可能消除很
多文字的命令会把消除掉的文字记录下来(它们被设定成了“可召回”),而那些 多文字的命令会把消除掉的文字记录下来(它们被设定成了“可召回”),而那些
只消除一个字符或者只消除空白的命令就不会记录被消除的内容(自然你也就无 只消除一个字符或者只消除空白的命令就不会记录被消除的内容(自然你也就无
法召回了)。<DEL> 和 C-d 在无前缀参数的情况下进行“删除”,而有前缀参数 法召回了)。
时则改用“移除”。
>> 移动光标到一非空白行的行头,然后输入 C-k 移除那一行上的文字。 >> 移动光标到一非空白行的行头,然后输入 C-k 移除那一行上的文字。
@ -360,11 +350,10 @@ Emacs 可以有多个“窗格”,每个窗格显示不同的文字。后面
C-k 会把两行以及它们的换行符移除;而如果只是输入 C-k 两次显然不是这个结 C-k 会把两行以及它们的换行符移除;而如果只是输入 C-k 两次显然不是这个结
果。 果。
【重新插入被移除的文字恢复的动作称为“召回yanking就好像把别人 重新插入被移除的文字恢复的动作称为“召回yanking”。就好像把别人从你身边
从你身边移走的东西又猛力地拉回来。】你可以在你删除文字的地方召回,也 移走的东西又猛力地拉回来。)你可以在你删除文字的地方召回,也可以在别的
可以在别的地方召回,还可以多次召回同样的文字以得到它的多个拷贝。很多其 地方召回,还可以多次召回同样的文字以得到它的多个拷贝。很多其它的编辑器
它的编辑器把移除和召回叫做“剪切”和“粘贴” (详情可见 Emacs 使用手册里的 把移除和召回叫做“剪切”和“粘贴” (详情可见 Emacs 使用手册里的术语表)。
术语表)。
召回的命令是 C-y。它会在光标所在处插入你最后移除的文字。 召回的命令是 C-y。它会在光标所在处插入你最后移除的文字。
@ -383,8 +372,8 @@ C-y 就可以把它们都召回。
C-y 可以召回最近一次移除的内容,那如何召回前几次移除的内容呢?它们当然 C-y 可以召回最近一次移除的内容,那如何召回前几次移除的内容呢?它们当然
没有丢,你可以用 M-y 来召回它们。在用 C-y 召回最近移除的文字之后,紧接 没有丢,你可以用 M-y 来召回它们。在用 C-y 召回最近移除的文字之后,紧接
着再按 M-y 就可以召回再前一次被移除的内容,再按一次 M-y 又可以召回再上 着再按 M-y 就可以召回再前一次被移除的内容,再按一次 M-y 又可以召回再上
一次的内容……连续使用 M-y 直到找到你想要召回的东西,然后什么也不用做, 一次的……连续使用 M-y 直到找到你想要召回的东西,然后什么也不用做,继续
继续编辑就行了。 编辑就行了。
如果连续按 M-y 很多次,你可能会回到起始点,也就是最近移除的文字。 如果连续按 M-y 很多次,你可能会回到起始点,也就是最近移除的文字。
【看得出这实际上是一个环。】 【看得出这实际上是一个环。】
@ -412,16 +401,14 @@ C-/,你会把以前的命令也依次撤销。
>> 用 C-k 将这一行移除,然后输入 C-/ ,它会再次出现。 >> 用 C-k 将这一行移除,然后输入 C-/ ,它会再次出现。
C-_ 也是撤销命令;它的作用跟 C-/ 一样,但是它比较容易多次输入。在某些 C-_ 也是撤销命令;它的作用跟 C-/ 一样,但是它比较容易多次输入。在
终端上,你可以不按 shift 键(即 C--)。在某些终端上,输入 C-/ 实际上向 某些终端上,输入 C-/ 实际上向 Emacs 发送的是 C-_ 。
Emacs 发送的是 C-_ 。另外, C-x u 和 C-/ 完全一样,但是按起来有些麻烦。 另外, C-x u 和 C-/ 完全一样,但是按起来有些麻烦。
数字参数对于 C-/ 、 C-_ 和 C-x u 的意义是执行撤销的重复次数。 数字参数对于 C-/ 、 C-_ 和 C-x u 的意义是执行撤销的重复次数。
你可以撤销文字的删除,就像你能撤销文字的移除一样。删除与移除的区别只在
于你是否能召回被影响的文字;对于撤销来说没有区别。
* 文件FILES * 文件FILE
-------------- --------------
想保存工作成果就要记得存盘,否则一旦退出 Emacs 你编辑的文字就会丢失。要 想保存工作成果就要记得存盘,否则一旦退出 Emacs 你编辑的文字就会丢失。要
@ -437,7 +424,7 @@ Emacs 发送的是 C-_ 。另外, C-x u 和 C-/ 完全一样,但是按起来
在屏幕的下方,你应该能够看到头部有短线“-”的一行,行首通常是一些诸如“ 在屏幕的下方,你应该能够看到头部有短线“-”的一行,行首通常是一些诸如“
-:--- TUTORIAL.cn”的文字这些文字代表了你当前正在访问的文件。比如你现 -:--- TUTORIAL.cn”的文字这些文字代表了你当前正在访问的文件。比如你现
在正在访问的文件是对 Emacs 快速指南的一份临时拷贝叫做“TUTORIAL.cn”。 在正在访问的文件是对 Emacs 快速指南的一份临时拷贝叫做“TUTORIAL.cn”。
每当 Emacs 寻找到一个文件,文件名就会出现在这个位置。 每当Emacs 寻找到一个文件,文件名就会出现在这个位置。
寻找文件的命令有一个特点,那就是你必须给出文件名。我们称这个命令“读入 寻找文件的命令有一个特点,那就是你必须给出文件名。我们称这个命令“读入
了一个参数”(在这里,这个参数显然就是文件名)。在你输入这条命令之后: 了一个参数”(在这里,这个参数显然就是文件名)。在你输入这条命令之后:
@ -448,14 +435,14 @@ Emacs 会提示你输入文件名。你输入的文件名会出现在屏幕最
行被称为小缓冲minibuffer在小缓冲里你可以使用通常的 Emacs 编辑命令 行被称为小缓冲minibuffer在小缓冲里你可以使用通常的 Emacs 编辑命令
来编辑文件名。 来编辑文件名。
在小缓冲里输入文件名(其实输入其它东西也一样)时可以用 C-g 取消这个命令 在小缓冲里输入文件名(其实输入其它东西也一样)时可以用 C-g 取消。
>> 输入 C-x C-f然后输入 C-g >> 输入 C-x C-f然后输入 C-g
这会关掉小缓冲,同时也会取消使用小缓冲的 C-x C-f 命令。 这会关掉小缓冲,同时也会取消使用小缓冲的 C-x C-f 命令。
当然了,你也没有找任何文件。 当然了,你也没有找任何文件。
当你写完要寻找的文件名时,用 <Return> 结束文件名的输入。之后,小缓冲会 用 <Return> 结束文件名的输入。之后,小缓冲会消失C-x C-f 将会去寻找你
消失C-x C-f 将会去寻找你指定的文件。 指定的文件。小缓冲在 C-x C-f 命令结束之后也会消失
文件被显示在了屏幕上,你可以开始编辑了。存盘用这条命令: 文件被显示在了屏幕上,你可以开始编辑了。存盘用这条命令:
@ -466,21 +453,20 @@ Emacs 会提示你输入文件名。你输入的文件名会出现在屏幕最
【对许多人来说,这是一个烦人的特性,关掉文件备份可以用如下命令: 【对许多人来说,这是一个烦人的特性,关掉文件备份可以用如下命令:
M-x customize-variable <Return> make-backup-files <Return>】 M-x customize-variable <Return> make-backup-files <Return>】
存盘结束后Emacs 会显示写入文件的文件名。【你最好养成经常存盘的习惯, 存盘结束后Emacs 会显示写入文件的文件名。你最好养成经常存盘的习惯,这
这可以减少系统崩溃和死机给你带来的损失(也可参见下面的“自动保存”一 可以减少系统崩溃和死机给你带来的损失(也可参见下面的“自动保存”一节)。
节)。】
>> 输入 C-x C-s TUTORIAL.cn <Return> 。 >> 输入 C-x C-s TUTORIAL.cn <Return> 。
这将会把该指南保存为一个名为 TUTORIAL.cn 的文件,并且在屏幕的下方显 这将会把该指南保存为一个名为 TUTORIAL.cn 的文件,并且在屏幕的下方显
示一条消息“Wrote TUTORIAL.cn”。 示一条消息“Wrote ...TUTORIAL.cn”。
你不但可以寻找一个已有的文件来查看或编辑,还可以寻找一个不存在的文件。 你不但可以寻找一个已有的文件来查看或编辑,还可以寻找一个不存在的文件。
实际上这正是 Emacs 创建新文件的方法:找到不存在的新文件,它一开始是空 实际上这正是 Emacs 创建新文件的方法:找到不存在的新文件。事实上,只有
的,然后你就可以开始插入文本。事实上,只有在存盘的时候Emacs 才会真正 在存盘的时候Emacs 才会真正创建这个文件。而在这之后的一切就跟编辑一个
创建这个文件。而在这之后的一切就跟编辑一个已有文件没有区别了。 已有文件没有区别了。
* 缓冲区BUFFERS * 缓冲区BUFFER
------------------ ------------------
你可以用 C-x C-f 找到并打开第二个文件,但第一个文件仍然在 Emacs 中。要 你可以用 C-x C-f 找到并打开第二个文件,但第一个文件仍然在 Emacs 中。要
@ -509,7 +495,7 @@ C-x C-f 是一种办法。不过还有一个更简单的办法,那就是用 C-
然后输入 C-x b TUTORIAL.cn <Return> 回到这里。 然后输入 C-x b TUTORIAL.cn <Return> 回到这里。
大多数情况下,缓冲区与跟其对应的文件是同名的(不包括目录名),不过这也 大多数情况下,缓冲区与跟其对应的文件是同名的(不包括目录名),不过这也
不是绝对的。因此用 C-x C-b 得到的缓冲区列表总是显示缓冲区名与文件名 不是绝对的。用 C-x C-b 得到的缓冲区列表总是显示缓冲区名。
缓冲区未必有对应文件。显示缓冲区列表的缓冲区(叫做“*Buffer List*”)就 缓冲区未必有对应文件。显示缓冲区列表的缓冲区(叫做“*Buffer List*”)就
是这样。这个 TUTORIAL.cn 缓冲区起初没有对应的文件,但是现在有了,因为 是这样。这个 TUTORIAL.cn 缓冲区起初没有对应的文件,但是现在有了,因为
@ -530,8 +516,8 @@ C-x C-f 是一种办法。不过还有一个更简单的办法,那就是用 C-
C-x s 保存多个缓冲区 C-x s 保存多个缓冲区
C-x s 会找出所有访问文件的、且已被修改但尚未存盘的缓冲区,然后向你逐个 C-x s 会找出所有已被修改但尚未存盘的缓冲区,然后向你逐个询问:是否需要
询问:是否需要存盘此文件 存盘
>> 插入一行文字,然后输入 C-x s。 >> 插入一行文字,然后输入 C-x s。
它应该会问你,是否要储存名为 TUTORIAL.cn 的缓冲区? 它应该会问你,是否要储存名为 TUTORIAL.cn 的缓冲区?
@ -568,9 +554,7 @@ C-x 的扩展命令有很多,下面列出的是你已经学过的:
C-x C-f 寻找文件。 C-x C-f 寻找文件。
C-x C-s 保存文件。 C-x C-s 保存文件。
C-x s 保存多个缓冲区。
C-x C-b 列出缓冲区。 C-x C-b 列出缓冲区。
C-x b 切换缓冲区。
C-x C-c 离开 Emacs。 C-x C-c 离开 Emacs。
C-x 1 关掉其它所有窗格,只保留一个。 C-x 1 关掉其它所有窗格,只保留一个。
C-x u 撤销。 C-x u 撤销。
@ -624,10 +608,10 @@ replace-string字符串替换这个命令它会把一个字符串替换
状态栏显示了 Emacs 的状态和你正在编辑的文字的一些信息。 状态栏显示了 Emacs 的状态和你正在编辑的文字的一些信息。
你应该知道文件名的意思吧就是你找到的那个文件嘛。NN% 显示的是光标在 你应该知道文件名的意思吧?就是你找到的那个文件嘛。-NN%-- 显示的是光标在
全文中的位置。如果位于文件的开头,那么就显示 Top 而不是 0%;如 全文中的位置。如果位于文件的开头,那么就显示 --Top-- 而不是 --00%--;如
果位于文件的末尾,就显示 Bot。如果文件很小一屏就足以显示全部内容 果位于文件的末尾,就显示 --Bot--。如果文件很小,一屏就足以显示全部内容,
那么状态栏会显示 All。 那么状态栏会显示 --All--
“L” 和其后的数字给出了光标所在行的行号。 “L” 和其后的数字给出了光标所在行的行号。
@ -739,10 +723,7 @@ C-s 是向前搜索C-r 是向后搜索。不过手别这么快!别着急试
* 多窗格MULTIPLE WINDOWS * 多窗格MULTIPLE WINDOWS
---------------------------- ----------------------------
Emacs 的迷人之处很多,能够在屏幕上同时显示多个窗格就是其中之一。(请注 Emacs 的迷人之处很多,能够在屏幕上同时显示多个窗格就是其中之一。
意在 Emacs 里的“窗口frame”与“窗格window”的定义可能与其他应用程
序不同详见Emacs 手册里的术语表。)【另见此教程末尾的翻译章节的术语译
词对照表。】
>> 移动光标到这一行,然后输入 C-l C-l。 >> 移动光标到这一行,然后输入 C-l C-l。
@ -801,13 +782,13 @@ Emacs 可以创建多个窗口。窗口由许多窗格以及菜单、滚动条
在图形界面下,多个窗口可以同时显示出来。在文本终端中,只能同时显示一个 在图形界面下,多个窗口可以同时显示出来。在文本终端中,只能同时显示一个
窗口。 窗口。
>> 输入 C-x 5 2 >> 输入 M-x make-frame <Return>
可以看到一个新的窗口出现在了你的屏幕上。 可以看到一个新的窗口出现在了你的屏幕上。
你可以在新的窗口里做最初的窗口里可以做的任何事情。第一个窗口没有什么特 你可以在新的窗口里做最初的窗口里可以做的任何事情。第一个窗口没有什么特
别的。 别的。
>> 输入 C-x 5 0。 >> 输入 M-x delete-frame <Return>.
这个命令将会关闭选中的窗口。 这个命令将会关闭选中的窗口。
你也可以通过图形系统来关闭某个窗口(通常是在窗口上面的某个角落里的一个 你也可以通过图形系统来关闭某个窗口(通常是在窗口上面的某个角落里的一个
@ -872,9 +853,9 @@ Emacs 可以创建多个窗口。窗口由许多窗格以及菜单、滚动条
还有一些其它有用的 C-h 命令: 还有一些其它有用的 C-h 命令:
C-h x 解释一个命令。需要输入命令名。 C-h f 解释一个函数。需要输入函数名。
>> 试试看,输入 C-h x previous-line <Return>。 >> 试试看,输入 C-h f previous-line <Return>。
Emacs 会给出它所知道的所有有关“实现 C-p 命令功能的函数”的信息。 Emacs 会给出它所知道的所有有关“实现 C-p 命令功能的函数”的信息。
C-h v 用来显示 Emacs 变量的文档。Emacs 变量可以被用来“定制 Emacs 的行 C-h v 用来显示 Emacs 变量的文档。Emacs 变量可以被用来“定制 Emacs 的行
@ -924,15 +905,15 @@ Dired 能够在一个缓冲区里列出一个目录下的所有文件(可以
Emacs 使用手册里还有许许多多的精彩功能等着你来了解。 Emacs 使用手册里还有许许多多的精彩功能等着你来了解。
* 安装软件INSTALLING PACKAGES * 安装包INSTALLING PACKAGES
--------------------------- ---------------------------
Emacs 社区著作了许多持有扩展性的软件packages其中包括对各种语言 Emacs 社区著作了许多持有扩展性的包packages其中包括对各种语言
支持、色彩鲜艳的主题、用于集成外部程序的软件包,等等。 支持、色彩鲜艳的主题、用于集成外部程序的包,等等。
使用 M-x list-packages 便可浏览所有可安装的软件包。这个命令显示的界面 使用 M-x list-packages 便可浏览存在的包裹。这个命令显示的界面中可以安
中可以安装和卸载软件包以及查看软件包的简介。Emacs 使用手册中有对软件 装和卸载包裹以及查看包裹的简介。Emacs 使用手册中有对包裹管理更详细的
包管理更详细的介绍。 介绍。
* 总结CONCLUSION * 总结CONCLUSION
-------------------- --------------------
@ -948,7 +929,6 @@ Emacs 社区著作了许多持有扩展性的软件包packages其中包
翻译:孙一江 <sunyijiang@gmail.com> 翻译:孙一江 <sunyijiang@gmail.com>
维护:薛富侨 <xfq.free@gmail.com> 维护:薛富侨 <xfq.free@gmail.com>
余睿杰 <ruijie@netyu.xyz>
校对水木社区www.newsmth.netEmacs 板众多网友及众多 Emacs 中文用户 校对水木社区www.newsmth.netEmacs 板众多网友及众多 Emacs 中文用户
Emacs 快速指南Tutorial早有两个刘昭宏的中文译本繁简各一。其简体版本 Emacs 快速指南Tutorial早有两个刘昭宏的中文译本繁简各一。其简体版本

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,6 @@ Maintainer: Ognyan Kulev <ogi@tower.3.bg>
* TUTORIAL.cn: * TUTORIAL.cn:
Author: Sun Yijiang <sunyijiang@gmail.com> Author: Sun Yijiang <sunyijiang@gmail.com>
Maintainer: Xue Fuqiao <xfq.free@gmail.com> Maintainer: Xue Fuqiao <xfq.free@gmail.com>
Ruijie Yu <ruijie@netyu.xyz>
* TUTORIAL.cs: * TUTORIAL.cs:
Author: Milan Zamazal <pdm@zamazal.org> Author: Milan Zamazal <pdm@zamazal.org>
@ -31,10 +30,6 @@ Maintainer: Rafael Sepúlveda <drs@gnulinux.org.mx>
Author: Protesilaos Stavrou <info@protesilaos.com> Author: Protesilaos Stavrou <info@protesilaos.com>
Maintainer: Protesilaos Stavrou <info@protesilaos.com> Maintainer: Protesilaos Stavrou <info@protesilaos.com>
* TUTORIAL.fa:
Author: Mohsen BANAN <emacs@mohsen.1.banan.byname.net>
Maintainer: Mohsen BANAN <emacs@mohsen.1.banan.byname.net>
* TUTORIAL.fr: * TUTORIAL.fr:
Author: Éric Jacoboni <jaco@teaser.fr> Author: Éric Jacoboni <jaco@teaser.fr>
Maintainer: Éric Jacoboni <jaco@teaser.fr> Maintainer: Éric Jacoboni <jaco@teaser.fr>

View file

@ -197,7 +197,7 @@
GAN 近緊跟根巾筋斤僅謹靳堇哏艮 GAN 近緊跟根巾筋斤僅謹靳堇哏艮
GANG 梗更庚羹館耿粳哽 GANG 梗更庚羹館耿粳哽
GAP 鴿蛤急 GAP 鴿蛤急
GAT <20><><EFBFBD> GAT <20><><EFBFBD>
GAU 究舊九夠苟狗垢玖韭久灸廄救咎疚摳鼽 GAU 究舊九夠苟狗垢玖韭久灸廄救咎疚摳鼽
GEI 幾記機基既紀技箕肌飢譏姬己伎寄忌妓剞嘰杞畿麂 GEI 幾記機基既紀技箕肌飢譏姬己伎寄忌妓剞嘰杞畿麂
GENG 鏡頸 GENG 鏡頸
@ -231,7 +231,7 @@
GWAI 櫃季瑰圭硅歸龜閨軌鬼詭桂跪貴悸巋饋匭匱劌皈 GWAI 櫃季瑰圭硅歸龜閨軌鬼詭桂跪貴悸巋饋匭匱劌皈
GWAN 君軍均滾棍鈞郡袞筠 GWAN 君軍均滾棍鈞郡袞筠
GWANG 轟 GWANG 轟
GWAT 癌备竇浑 GWAT 癌备竇浑
GWING 炯 GWING 炯
GWOH 過果戈裹棵顆錁 GWOH 過果戈裹棵顆錁
GWOK 郭國廓 GWOK 郭國廓

View file

@ -72,10 +72,9 @@ AUTOGENEL = ${loaddefs} ${srcdir}/cus-load.el ${srcdir}/finder-inf.el \
${srcdir}/subdirs.el ${srcdir}/eshell/esh-groups.el ${srcdir}/subdirs.el ${srcdir}/eshell/esh-groups.el
# Set load-prefer-newer for the benefit of the non-bootstrappers. # Set load-prefer-newer for the benefit of the non-bootstrappers.
# Set org--inhibit-version-check to avoid unnecessarily aborting the build.
BYTE_COMPILE_FLAGS = \ BYTE_COMPILE_FLAGS = \
--eval "(setq load-prefer-newer t byte-compile-warnings 'all)" \ --eval "(setq load-prefer-newer t byte-compile-warnings 'all)" \
--eval "(setq org--inhibit-version-check t)" $(BYTE_COMPILE_EXTRA_FLAGS) $(BYTE_COMPILE_EXTRA_FLAGS)
# ... but we must prefer .elc files for those in the early bootstrap. # ... but we must prefer .elc files for those in the early bootstrap.
compile-first: BYTE_COMPILE_FLAGS = $(BYTE_COMPILE_EXTRA_FLAGS) compile-first: BYTE_COMPILE_FLAGS = $(BYTE_COMPILE_EXTRA_FLAGS)
@ -490,8 +489,8 @@ check-declare:
## This finds a lot of duplicates between foo.el and obsolete/foo.el. ## This finds a lot of duplicates between foo.el and obsolete/foo.el.
check-defun-dups: check-defun-dups:
sed -n -e '/^(defun /s/\(.\)(.*/\1/p' \ sed -n -e '/^(defun /s/\(.\)(.*/\1/p' \
`find . -name '*.el' ! -name '.*' -print | \ $$(find . -name '*.el' ! -name '.*' -print | \
grep -Ev '(loaddefs|ldefs-boot)\.el|obsolete'` | sort | uniq -d grep -Ev '(loaddefs|ldefs-boot)\.el|obsolete') | sort | uniq -d
# Dependencies # Dependencies

View file

@ -5390,7 +5390,7 @@ Defaults:
;; not specified -- default it: ;; not specified -- default it:
(setq tobuf (concat "*" (buffer-name frombuf) " exposed*"))) (setq tobuf (concat "*" (buffer-name frombuf) " exposed*")))
(if (listp format) (if (listp format)
(setq format (reverse format))) (nreverse format))
(let* ((listified (let* ((listified
(progn (set-buffer frombuf) (progn (set-buffer frombuf)

View file

@ -645,49 +645,6 @@ Does not signal an error if optional argument NOERROR is non-nil."
(if (not noerror) (if (not noerror)
(error "Line does not describe a member of the archive"))))) (error "Line does not describe a member of the archive")))))
;; ------------------------------------------------------------------------- ;; -------------------------------------------------------------------------
;;; Section: Helper functions for requiring filename extensions
(defun archive--act-files (command files)
(lambda (archive)
(apply #'call-process (car command)
nil nil nil (append (cdr command) (cons archive files)))))
(defun archive--need-rename-p (&optional archive)
(let ((archive
(file-name-nondirectory (or archive buffer-file-name))))
(cl-case archive-subtype
((zip) (not (seq-contains-p archive ?. #'eq))))))
(defun archive--ensure-extension (archive ensure-extension)
(if ensure-extension
(make-temp-name (expand-file-name (concat archive "_tmp.")))
archive))
(defun archive--maybe-rename (newname need-rename-p)
;; Operating with archive as current buffer, and protect
;; `default-directory' from being modified in `rename-visited-file'.
(when need-rename-p
(let ((default-directory default-directory))
(rename-visited-file newname))))
(defun archive--with-ensure-extension (archive proc-fn)
(let ((saved default-directory))
(with-current-buffer (find-buffer-visiting archive)
(let ((ensure-extension (archive--need-rename-p))
(default-directory saved))
(unwind-protect
;; Some archive programs (like zip) expect filenames to
;; have an extension, so if necessary, temporarily rename
;; an extensionless file for write accesses.
(let ((archive (archive--ensure-extension
archive ensure-extension)))
(archive--maybe-rename archive ensure-extension)
(let ((exitcode (funcall proc-fn archive)))
(or (zerop exitcode)
(error "Updating was unsuccessful (%S)" exitcode))))
(progn (archive--maybe-rename archive ensure-extension)
(revert-buffer nil t)))))))
;; -------------------------------------------------------------------------
;;; Section: the mode definition ;;; Section: the mode definition
;;;###autoload ;;;###autoload
@ -1421,9 +1378,16 @@ NEW-NAME."
(setq ename (setq ename
(encode-coding-string ename archive-file-name-coding-system)) (encode-coding-string ename archive-file-name-coding-system))
(let* ((coding-system-for-write 'no-conversion) (let* ((coding-system-for-write 'no-conversion)
(default-directory (file-name-as-directory archive-tmpdir))) (default-directory (file-name-as-directory archive-tmpdir))
(archive--with-ensure-extension (exitcode (apply #'call-process
archive (archive--act-files command (list ename))))) (car command)
nil
nil
nil
(append (cdr command)
(list archive ename)))))
(or (zerop exitcode)
(error "Updating was unsuccessful (%S)" exitcode))))
(archive-delete-local tmpfile)))) (archive-delete-local tmpfile))))
(defun archive-write-file (&optional file) (defun archive-write-file (&optional file)
@ -1546,7 +1510,9 @@ as a relative change like \"g+rw\" as for chmod(2)."
(archive-resummarize)) (archive-resummarize))
(error "Setting group is not supported for this archive type")))) (error "Setting group is not supported for this archive type"))))
(defun archive--expunge-maybe-force (force) (defun archive-expunge ()
"Do the flagged deletions."
(interactive)
(let (files) (let (files)
(save-excursion (save-excursion
(goto-char archive-file-list-start) (goto-char archive-file-list-start)
@ -1560,8 +1526,7 @@ as a relative change like \"g+rw\" as for chmod(2)."
(and files (and files
(or (not archive-read-only) (or (not archive-read-only)
(error "Archive is read-only")) (error "Archive is read-only"))
(or force (or (yes-or-no-p (format "Really delete %d member%s? "
(yes-or-no-p (format "Really delete %d member%s? "
(length files) (length files)
(if (null (cdr files)) "" "s"))) (if (null (cdr files)) "" "s")))
(error "Operation aborted")) (error "Operation aborted"))
@ -1575,14 +1540,13 @@ as a relative change like \"g+rw\" as for chmod(2)."
(archive-resummarize) (archive-resummarize)
(revert-buffer)))))) (revert-buffer))))))
(defun archive-expunge ()
"Do the flagged deletions."
(interactive)
(archive--expunge-maybe-force nil))
(defun archive-*-expunge (archive files command) (defun archive-*-expunge (archive files command)
(archive--with-ensure-extension (apply #'call-process
archive (archive--act-files command files))) (car command)
nil
nil
nil
(append (cdr command) (cons archive files))))
(defun archive-rename-entry (newname) (defun archive-rename-entry (newname)
"Change the name associated with this entry in the archive file." "Change the name associated with this entry in the archive file."

View file

@ -195,6 +195,7 @@ Calc user interface as before (either \\`C-x * C' or \\`C-x * K'; initially \\`C
;;;###autoload ;;;###autoload
(defun calc-info-goto-node (node) (defun calc-info-goto-node (node)
"Go to a node in the Calculator info documentation." "Go to a node in the Calculator info documentation."
(interactive)
(select-window (get-largest-window)) (select-window (get-largest-window))
(info (concat "(Calc)" node))) (info (concat "(Calc)" node)))

View file

@ -936,6 +936,7 @@
(defun calc-edit-macro-finish-edit (cmdname key) (defun calc-edit-macro-finish-edit (cmdname key)
"Finish editing a Calc macro. "Finish editing a Calc macro.
Redefine the corresponding command." Redefine the corresponding command."
(interactive)
(let ((cmd (intern cmdname))) (let ((cmd (intern cmdname)))
(calc-edit-macro-pre-finish-edit) (calc-edit-macro-pre-finish-edit)
(let* ((str (buffer-substring calc-edit-top (point-max))) (let* ((str (buffer-substring calc-edit-top (point-max)))

View file

@ -1349,9 +1349,8 @@ Optional string argument KEYS will force using it as the keys entered."
(calculator-update-display t)) (calculator-update-display t))
(defun calculator-saved-move (n) (defun calculator-saved-move (n)
"Go N elements up the list of saved values. "Go N elements up the list of saved values."
Interactively, N is the prefix numeric argument and defaults to 1." (interactive)
(interactive "p")
(when (and calculator-saved-list (when (and calculator-saved-list
(or (null calculator-stack) calculator-display-fragile)) (or (null calculator-stack) calculator-display-fragile))
(setq calculator-saved-ptr (setq calculator-saved-ptr

View file

@ -147,7 +147,7 @@ letters, digits, plus or minus signs or colons."
;;;###autoload(put 'parse-time-rules 'risky-local-variable t) ;;;###autoload(put 'parse-time-rules 'risky-local-variable t)
;;;###autoload ;;;###autoload
(defun parse-time-string (string &optional form) (defun parse-time-string (string)
"Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ). "Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
STRING should be an ISO 8601 time string, e.g., \"2020-01-15T16:12:21-08:00\", STRING should be an ISO 8601 time string, e.g., \"2020-01-15T16:12:21-08:00\",
or something resembling an RFC 822 (or later) date-time, e.g., or something resembling an RFC 822 (or later) date-time, e.g.,
@ -156,11 +156,9 @@ somewhat liberal in what format it accepts, and will attempt to
return a \"likely\" value even for somewhat malformed strings. return a \"likely\" value even for somewhat malformed strings.
The values returned are identical to those of `decode-time', but The values returned are identical to those of `decode-time', but
any unknown values other than DST are returned as nil, and an any unknown values other than DST are returned as nil, and an
unknown DST value is returned as -1. unknown DST value is returned as -1."
See `decode-time' for the meaning of FORM."
(condition-case () (condition-case ()
(iso8601-parse string form) (iso8601-parse string)
(wrong-type-argument (wrong-type-argument
(let ((time (list nil nil nil nil nil nil nil -1 nil)) (let ((time (list nil nil nil nil nil nil nil -1 nil))
(temp (parse-time-tokenize (downcase string)))) (temp (parse-time-tokenize (downcase string))))
@ -201,14 +199,12 @@ See `decode-time' for the meaning of FORM."
(setf (nth (pop slots) time) new-val)))))))) (setf (nth (pop slots) time) new-val))))))))
time)))) time))))
(defun parse-iso8601-time-string (date-string &optional form) (defun parse-iso8601-time-string (date-string)
"Parse an ISO 8601 time string, such as \"2020-01-15T16:12:21-08:00\". "Parse an ISO 8601 time string, such as \"2020-01-15T16:12:21-08:00\".
Fall back on parsing something resembling an RFC 822 (or later) date-time. Fall back on parsing something resembling an RFC 822 (or later) date-time.
This function is like `parse-time-string' except that it returns This function is like `parse-time-string' except that it returns
a Lisp timestamp when successful. a Lisp timestamp when successful."
(when-let ((time (parse-time-string date-string)))
See `decode-time' for the meaning of FORM."
(when-let ((time (parse-time-string date-string form)))
(encode-time time))) (encode-time time)))
(provide 'parse-time) (provide 'parse-time)

View file

@ -618,7 +618,9 @@ Does nothing if the current buffer doesn't need reparsing."
(lexically-safe t) (lexically-safe t)
) )
(unwind-protect
;; Perform the parsing. ;; Perform the parsing.
(progn
(when (semantic-lex-catch-errors safe-refresh (when (semantic-lex-catch-errors safe-refresh
(save-excursion (semantic-fetch-tags)) (save-excursion (semantic-fetch-tags))
nil) nil)
@ -629,7 +631,8 @@ Does nothing if the current buffer doesn't need reparsing."
;; to go off. In the meantime, remember this, and make sure ;; to go off. In the meantime, remember this, and make sure
;; no other idle services can get executed. ;; no other idle services can get executed.
(setq lexically-safe nil)) (setq lexically-safe nil))
)
)
;; Return if we are lexically safe ;; Return if we are lexically safe
lexically-safe)))) lexically-safe))))

View file

@ -927,9 +927,9 @@ marked file, return (t FILENAME) instead of (FILENAME)."
(lambda () (lambda ()
(if ,show-progress (sit-for 0)) (if ,show-progress (sit-for 0))
(setq results (cons ,body results)))) (setq results (cons ,body results))))
(when (< ,arg 0) (if (< ,arg 0)
(setq results (nreverse results))) (nreverse results)
results) results))
;; non-nil, non-integer, non-marked ARG means use current file: ;; non-nil, non-integer, non-marked ARG means use current file:
(list ,body)) (list ,body))
(let ((regexp (dired-marker-regexp)) next-position) (let ((regexp (dired-marker-regexp)) next-position)
@ -1647,16 +1647,13 @@ If HDR is non-nil, insert a header line with the directory name."
;; save the answer in `dired-use-ls-dired'. ;; save the answer in `dired-use-ls-dired'.
(or (setq dired-use-ls-dired (or (setq dired-use-ls-dired
(eq 0 (call-process insert-directory-program (eq 0 (call-process insert-directory-program
nil nil nil "--dired" "-N"))) nil nil nil "--dired")))
(progn (progn
(message "ls does not support --dired -N; \ (message "ls does not support --dired; \
see `dired-use-ls-dired' for more details.") see `dired-use-ls-dired' for more details.")
nil)) nil))
dired-use-ls-dired))) dired-use-ls-dired)))
;; Use -N with --dired, to countermand possible non-default (setq switches (concat "--dired " switches)))
;; quoting style, in particular via the environment variable
;; QUOTING_STYLE.
(setq switches (concat "--dired -N " switches)))
;; Expand directory wildcards and fill file-list. ;; Expand directory wildcards and fill file-list.
(let ((dir-wildcard (insert-directory-wildcard-in-dir-p dir))) (let ((dir-wildcard (insert-directory-wildcard-in-dir-p dir)))
(cond (dir-wildcard (cond (dir-wildcard
@ -1665,7 +1662,7 @@ see `dired-use-ls-dired' for more details.")
;; "--dired", so we cannot add it to the `process-file' ;; "--dired", so we cannot add it to the `process-file'
;; call for wildcards. ;; call for wildcards.
(when (file-remote-p dir) (when (file-remote-p dir)
(setq switches (string-replace "--dired -N" "" switches))) (setq switches (string-replace "--dired" "" switches)))
(let* ((default-directory (car dir-wildcard)) (let* ((default-directory (car dir-wildcard))
(script (format "ls %s %s" switches (cdr dir-wildcard))) (script (format "ls %s %s" switches (cdr dir-wildcard)))
(remotep (file-remote-p dir)) (remotep (file-remote-p dir))

View file

@ -409,7 +409,9 @@ If multiple rules match, only first one is executed.")
(goto-char pos) (goto-char pos)
(funcall probe last-command-event)))) (funcall probe last-command-event))))
(when res (throw 'done res)))))))))) (when res (throw 'done res))))))))))
(when rule (when (and rule
;; Not in a string or comment.
(not (nth 8 (save-excursion (syntax-ppss pos)))))
(goto-char pos) (goto-char pos)
(when (functionp rule) (setq rule (funcall rule))) (when (functionp rule) (setq rule (funcall rule)))
(dolist (sym (if (symbolp rule) (list rule) rule)) (dolist (sym (if (symbolp rule) (list rule) rule))

View file

@ -499,6 +499,7 @@ Reprint the frame with the new view plist."
(defun backtrace-expand-ellipsis (button) (defun backtrace-expand-ellipsis (button)
"Expand display of the elided form at BUTTON." "Expand display of the elided form at BUTTON."
(interactive)
(goto-char (button-start button)) (goto-char (button-start button))
(unless (get-text-property (point) 'cl-print-ellipsis) (unless (get-text-property (point) 'cl-print-ellipsis)
(if (and (> (point) (point-min)) (if (and (> (point) (point-min))

View file

@ -221,17 +221,21 @@ for speeding up processing.")
(defun byte-optimize--substitutable-p (expr) (defun byte-optimize--substitutable-p (expr)
"Whether EXPR is a constant that can be propagated." "Whether EXPR is a constant that can be propagated."
;; Only consider numbers, symbols and strings to be values for substitution
;; purposes. Numbers and symbols are immutable, and mutating string
;; literals (or results from constant-evaluated string-returning functions)
;; can be considered undefined.
;; (What about other quoted values, like conses?)
(or (booleanp expr) (or (booleanp expr)
(numberp expr) (numberp expr)
(arrayp expr) (stringp expr)
(let ((head (car-safe expr))) (and (consp expr)
(cond ((eq head 'quote) t) (or (and (memq (car expr) '(quote function))
;; Don't substitute #'(lambda ...) since that would enable (symbolp (cadr expr)))
;; uncontrolled inlining.
((eq head 'function) (symbolp (cadr expr)))
;; (internal-get-closed-var N) can be considered constant for ;; (internal-get-closed-var N) can be considered constant for
;; const-prop purposes. ;; const-prop purposes.
((eq head 'internal-get-closed-var) (integerp (cadr expr))))) (and (eq (car expr) 'internal-get-closed-var)
(integerp (cadr expr)))))
(keywordp expr))) (keywordp expr)))
(defmacro byte-optimize--pcase (exp &rest cases) (defmacro byte-optimize--pcase (exp &rest cases)
@ -465,6 +469,10 @@ for speeding up processing.")
form form
(byte-optimize-form newform for-effect)))) (byte-optimize-form newform for-effect))))
;; FIXME: Strictly speaking, I think this is a bug: (closure...)
;; is a *value* and shouldn't appear in the car.
(`((closure . ,_) . ,_) form)
(`(setq ,var ,expr) (`(setq ,var ,expr)
(let ((lexvar (assq var byte-optimize--lexvars)) (let ((lexvar (assq var byte-optimize--lexvars))
(value (byte-optimize-form expr nil))) (value (byte-optimize-form expr nil)))
@ -492,13 +500,19 @@ for speeding up processing.")
(cons fn (mapcar #'byte-optimize-form exps))) (cons fn (mapcar #'byte-optimize-form exps)))
(`(,(pred (not symbolp)) . ,_) (`(,(pred (not symbolp)) . ,_)
(byte-compile-warn-x form "`%s' is a malformed function" fn) (byte-compile-warn-x fn "`%s' is a malformed function" fn)
form) form)
((guard (when for-effect ((guard (when for-effect
(if-let ((tmp (byte-opt--fget fn 'side-effect-free))) (if-let ((tmp (byte-opt--fget fn 'side-effect-free)))
(or byte-compile-delete-errors (or byte-compile-delete-errors
(eq tmp 'error-free))))) (eq tmp 'error-free)
(progn
(byte-compile-warn-x
form
"value returned from %s is unused"
form)
nil)))))
(byte-compile-log " %s called for effect; deleted" fn) (byte-compile-log " %s called for effect; deleted" fn)
(byte-optimize-form (cons 'progn (cdr form)) t)) (byte-optimize-form (cons 'progn (cdr form)) t))
@ -1412,13 +1426,10 @@ See Info node `(elisp) Integer Basics'."
(defun byte-optimize-funcall (form) (defun byte-optimize-funcall (form)
;; (funcall #'(lambda ...) ...) -> ((lambda ...) ...) ;; (funcall (lambda ...) ...) ==> ((lambda ...) ...)
;; (funcall #'SYM ...) -> (SYM ...) ;; (funcall foo ...) ==> (foo ...)
;; (funcall 'SYM ...) -> (SYM ...) (let ((fn (nth 1 form)))
(let* ((fn (nth 1 form)) (if (memq (car-safe fn) '(quote function))
(head (car-safe fn)))
(if (or (eq head 'function)
(and (eq head 'quote) (symbolp (nth 1 fn))))
(cons (nth 1 fn) (cdr (cdr form))) (cons (nth 1 fn) (cdr (cdr form)))
form))) form)))
@ -1515,44 +1526,6 @@ See Info node `(elisp) Integer Basics'."
;; (list) -> nil ;; (list) -> nil
(and (cdr form) form)) (and (cdr form) form))
(put 'nconc 'byte-optimizer #'byte-optimize-nconc)
(defun byte-optimize-nconc (form)
(pcase (cdr form)
('nil nil) ; (nconc) -> nil
(`(,x) x) ; (nconc X) -> X
(_ (named-let loop ((args (cdr form)) (newargs nil))
(if args
(let ((arg (car args))
(prev (car newargs)))
(cond
;; Elide null args.
((and (null arg)
;; Don't elide a terminal nil unless preceded by
;; a nonempty proper list, since that will have
;; its last cdr forced to nil.
(or (cdr args)
;; FIXME: prove the 'nonempty proper list' property
;; for more forms than just `list', such as
;; `append', `mapcar' etc.
(eq 'list (car-safe (car newargs)))))
(loop (cdr args) newargs))
;; Merge consecutive `list' args.
((and (eq (car-safe arg) 'list)
(eq (car-safe prev) 'list))
(loop (cons (cons (car prev) (append (cdr prev) (cdr arg)))
(cdr args))
(cdr newargs)))
;; (nconc ... (list A) B ...) -> (nconc ... (cons A B) ...)
((and (eq (car-safe prev) 'list) (cdr prev) (null (cddr prev)))
(loop (cdr args)
(cons (list 'cons (cadr prev) arg)
(cdr newargs))))
(t (loop (cdr args) (cons arg newargs)))))
(let ((new-form (cons (car form) (nreverse newargs))))
(if (equal new-form form)
form
new-form)))))))
(put 'append 'byte-optimizer #'byte-optimize-append) (put 'append 'byte-optimizer #'byte-optimize-append)
(defun byte-optimize-append (form) (defun byte-optimize-append (form)
;; There is (probably) too much code relying on `append' to return a ;; There is (probably) too much code relying on `append' to return a
@ -1605,9 +1578,11 @@ See Info node `(elisp) Integer Basics'."
;; (append X) -> X ;; (append X) -> X
((null newargs) arg) ((null newargs) arg)
;; (append ... (list Xs...) nil) -> (append ... (list Xs...)) ;; (append (list Xs...) nil) -> (list Xs...)
((and (null arg) (eq (car-safe prev) 'list)) ((and (null arg)
(cons (car form) (nreverse newargs))) newargs (null (cdr newargs))
(consp prev) (eq (car prev) 'list))
prev)
;; (append '(X) Y) -> (cons 'X Y) ;; (append '(X) Y) -> (cons 'X Y)
;; (append (list X) Y) -> (cons X Y) ;; (append (list X) Y) -> (cons X Y)
@ -1618,13 +1593,13 @@ See Info node `(elisp) Integer Basics'."
(= (length (cadr prev)) 1))) (= (length (cadr prev)) 1)))
((eq (car prev) 'list) ((eq (car prev) 'list)
(= (length (cdr prev)) 1)))) (= (length (cdr prev)) 1))))
`(cons ,(if (eq (car prev) 'quote) (list 'cons (if (eq (car prev) 'quote)
(macroexp-quote (caadr prev)) (macroexp-quote (caadr prev))
(cadr prev)) (cadr prev))
,arg)) arg))
(t (t
(let ((new-form (cons (car form) (nreverse (cons arg newargs))))) (let ((new-form (cons 'append (nreverse (cons arg newargs)))))
(if (equal new-form form) (if (equal new-form form)
form form
new-form)))))))) new-form))))))))
@ -1667,231 +1642,98 @@ See Info node `(elisp) Integer Basics'."
;; I wonder if I missed any :-\) ;; I wonder if I missed any :-\)
(let ((side-effect-free-fns (let ((side-effect-free-fns
'( '(% * + - / /= 1+ 1- < <= = > >= abs acos append aref ash asin atan
;; alloc.c assq
make-bool-vector make-byte-code make-list make-record make-string base64-decode-string base64-encode-string base64url-encode-string
make-symbol make-vector
;; buffer.c
buffer-base-buffer buffer-chars-modified-tick buffer-file-name
buffer-local-value buffer-local-variables buffer-modified-p
buffer-modified-tick buffer-name get-buffer next-overlay-change
overlay-buffer overlay-end overlay-get overlay-properties
overlay-start overlays-at overlays-in previous-overlay-change
;; callint.c
prefix-numeric-value
;; casefiddle.c
capitalize downcase upcase upcase-initials
;; category.c
category-docstring category-set-mnemonics char-category-set
copy-category-table get-unused-category make-category-set
;; character.c
char-width multibyte-char-to-unibyte string unibyte-char-to-multibyte
;; charset.c
decode-char encode-char
;; chartab.c
make-char-table
;; data.c
% * + - / /= 1+ 1- < <= = > >=
aref ash bare-symbol
bool-vector-count-consecutive bool-vector-count-population bool-vector-count-consecutive bool-vector-count-population
bool-vector-subsetp bool-vector-subsetp
boundp car cdr default-boundp default-value fboundp boundp buffer-file-name buffer-local-variables buffer-modified-p
get-variable-watchers indirect-variable buffer-substring byte-code-function-p
local-variable-if-set-p local-variable-p capitalize car-less-than-car car cdr ceiling char-after char-before
logand logcount logior lognot logxor max min mod char-equal char-to-string char-width compare-strings
number-to-string position-symbol string-to-number window-configuration-equal-p concat coordinates-in-window-p
subr-arity subr-name subr-native-lambda-list subr-type copy-alist copy-sequence copy-marker copysign cos
current-time-string current-time-zone
decode-char
decode-time default-boundp default-value documentation downcase
elt encode-char exp expt encode-time error-message-string
fboundp fceiling featurep ffloor
file-directory-p file-exists-p file-locked-p file-name-absolute-p
file-name-concat
file-newer-than-file-p file-readable-p file-symlink-p file-writable-p
float float-time floor format format-message format-time-string
frame-first-window frame-root-window frame-selected-window
frame-visible-p fround ftruncate
get gethash get-buffer get-buffer-window get-file-buffer
hash-table-count
intern-soft isnan
keymap-parent
ldexp
length length< length> length=
line-beginning-position line-end-position pos-bol pos-eol
local-variable-if-set-p local-variable-p locale-info
log logand logb logcount logior lognot logxor
make-byte-code make-list make-string make-symbol marker-buffer max
match-beginning match-end
member memq memql min minibuffer-selected-window minibuffer-window
mod multibyte-char-to-unibyte next-window nth nthcdr number-to-string
prefix-numeric-value previous-window prin1-to-string propertize
rassq rassoc read-from-string
regexp-quote region-beginning region-end reverse round
sin sqrt string string-equal string-lessp
string-search string-to-char
string-to-number string-to-syntax substring substring-no-properties
sxhash-equal sxhash-eq sxhash-eql
symbol-function symbol-name symbol-plist symbol-value symbol-function symbol-name symbol-plist symbol-value
symbol-with-pos-pos variable-binding-locus string-make-unibyte
;; doc.c string-make-multibyte string-as-multibyte string-as-unibyte
documentation string-to-multibyte
;; editfns.c take tan time-convert truncate
buffer-substring buffer-substring-no-properties unibyte-char-to-multibyte upcase user-full-name
byte-to-position byte-to-string user-login-name
char-after char-before char-equal char-to-string vconcat
compare-buffer-substrings window-at window-body-height
format format-message window-body-width window-buffer window-dedicated-p window-display-table
group-name window-combination-limit window-frame window-fringes
line-beginning-position line-end-position ngettext pos-bol pos-eol window-hscroll
propertize region-beginning region-end string-to-char window-left-child window-left-column window-margins window-minibuffer-p
user-full-name user-login-name window-next-buffers window-next-sibling window-new-normal
;; fileio.c window-new-total window-normal-size window-parameter window-parameters
car-less-than-car directory-name-p file-directory-p file-exists-p window-parent window-point window-prev-buffers
file-name-absolute-p file-name-concat file-newer-than-file-p window-prev-sibling window-scroll-bars
file-readable-p file-symlink-p file-writable-p
;; filelock.c
file-locked-p
;; floatfns.c
abs acos asin atan ceiling copysign cos exp expt fceiling ffloor
float floor fround ftruncate isnan ldexp log logb round sin sqrt tan
truncate
;; fns.c
append assq
base64-decode-string base64-encode-string base64url-encode-string
compare-strings concat copy-alist copy-hash-table copy-sequence elt
featurep get
gethash hash-table-count hash-table-rehash-size
hash-table-rehash-threshold hash-table-size hash-table-test
hash-table-weakness
length length< length= length>
line-number-at-pos locale-info make-hash-table
member memq memql nth nthcdr
object-intervals rassoc rassq reverse
string-as-multibyte string-as-unibyte string-bytes string-distance
string-equal string-lessp string-make-multibyte string-make-unibyte
string-search string-to-multibyte substring substring-no-properties
sxhash-eq sxhash-eql sxhash-equal sxhash-equal-including-properties
take vconcat
;; frame.c
frame-ancestor-p frame-bottom-divider-width frame-char-height
frame-char-width frame-child-frame-border-width frame-focus
frame-fringe-width frame-internal-border-width frame-native-height
frame-native-width frame-parameter frame-parameters frame-parent
frame-pointer-visible-p frame-position frame-right-divider-width
frame-scale-factor frame-scroll-bar-height frame-scroll-bar-width
frame-text-cols frame-text-height frame-text-lines frame-text-width
frame-total-cols frame-total-lines frame-visible-p
frame-window-state-change next-frame previous-frame
tool-bar-pixel-width window-system
;; fringe.c
fringe-bitmaps-at-pos
;; keyboard.c
posn-at-point posn-at-x-y
;; keymap.c
copy-keymap keymap-parent keymap-prompt make-keymap make-sparse-keymap
;; lread.c
intern-soft read-from-string
;; marker.c
copy-marker marker-buffer marker-insertion-type marker-position
;; minibuf.c
active-minibuffer-window assoc-string innermost-minibuffer-p
minibuffer-innermost-command-loop-p minibufferp
;; print.c
error-message-string prin1-to-string
;; process.c
format-network-address get-buffer-process get-process
process-buffer process-coding-system process-command process-filter
process-id process-inherit-coding-system-flag process-mark
process-name process-plist process-query-on-exit-flag
process-running-child-p process-sentinel process-thread
process-tty-name process-type
;; search.c
match-beginning match-end regexp-quote
;; sqlite.c
sqlite-columns sqlite-more-p sqlite-version
;; syntax.c
char-syntax copy-syntax-table matching-paren string-to-syntax
syntax-class-to-char
;; term.c
controlling-tty-p tty-display-color-cells tty-display-color-p
tty-top-frame tty-type
;; terminal.c
frame-terminal terminal-list terminal-live-p terminal-name
terminal-parameter terminal-parameters
;; textprop.c
get-char-property get-char-property-and-overlay get-text-property
next-char-property-change next-property-change
next-single-char-property-change next-single-property-change
previous-char-property-change previous-property-change
previous-single-char-property-change previous-single-property-change
text-properties-at text-property-any text-property-not-all
;; thread.c
all-threads condition-mutex condition-name mutex-name thread-live-p
thread-name
;; timefns.c
current-time-string current-time-zone decode-time encode-time
float-time format-time-string time-add time-convert time-equal-p
time-less-p time-subtract
;; window.c
coordinates-in-window-p frame-first-window frame-root-window
frame-selected-window get-buffer-window minibuffer-selected-window
minibuffer-window next-window previous-window window-at
window-body-height window-body-width window-buffer
window-combination-limit window-configuration-equal-p
window-dedicated-p window-display-table window-frame window-fringes
window-hscroll window-left-child window-left-column window-margins
window-minibuffer-p window-new-normal window-new-total
window-next-buffers window-next-sibling window-normal-size
window-parameter window-parameters window-parent window-point
window-prev-buffers window-prev-sibling window-scroll-bars
window-start window-text-height window-top-child window-top-line window-start window-text-height window-top-child window-top-line
window-total-height window-total-width window-use-time window-vscroll window-total-height window-total-width window-use-time window-vscroll
;; xdisp.c
buffer-text-pixel-size current-bidi-paragraph-direction
get-display-property invisible-p line-pixel-height lookup-image-map
tab-bar-height tool-bar-height window-text-pixel-size
)) ))
(side-effect-and-error-free-fns (side-effect-and-error-free-fns
'( '(arrayp atom
;; alloc.c bobp bolp bool-vector-p
bool-vector cons list make-marker purecopy record vector buffer-list buffer-size buffer-string bufferp
;; buffer.c car-safe case-table-p cdr-safe char-or-string-p characterp
buffer-list buffer-live-p current-buffer overlay-lists overlayp charsetp commandp cons consp
;; casetab.c current-buffer current-global-map current-indentation
case-table-p current-case-table standard-case-table current-local-map current-minor-mode-maps current-time
;; category.c eobp eolp eq equal
category-table category-table-p make-category-table floatp following-char framep
standard-category-table hash-table-p
;; character.c identity indirect-function integerp integer-or-marker-p
characterp max-char
;; charset.c
charsetp
;; data.c
arrayp atom bare-symbol-p bool-vector-p bufferp byte-code-function-p
byteorder car-safe cdr-safe char-or-string-p char-table-p
condition-variable-p consp eq floatp indirect-function
integer-or-marker-p integerp keywordp listp markerp
module-function-p multibyte-string-p mutexp natnump nlistp null
number-or-marker-p numberp recordp remove-pos-from-symbol
sequencep stringp subr-native-elisp-p subrp symbol-with-pos-p symbolp
threadp type-of user-ptrp vector-or-char-table-p vectorp wholenump
;; editfns.c
bobp bolp buffer-size buffer-string current-message emacs-pid
eobp eolp following-char gap-position gap-size group-gid
group-real-gid mark-marker point point-marker point-max point-min
position-bytes preceding-char system-name
user-real-login-name user-real-uid user-uid
;; emacs.c
invocation-directory invocation-name invocation-directory invocation-name
;; eval.c keymapp keywordp
commandp functionp list listp
;; fileio.c make-marker mark-marker markerp max-char
default-file-modes natnump nlistp null number-or-marker-p numberp
;; fns.c overlayp
eql equal hash-table-p identity proper-list-p safe-length point point-marker point-min point-max preceding-char
secure-hash-algorithms processp proper-list-p
;; frame.c recent-keys recursion-depth
frame-list frame-live-p framep last-nonminibuffer-frame safe-length selected-frame selected-window sequencep
old-selected-frame selected-frame visible-frame-list standard-case-table standard-syntax-table stringp subrp symbolp
;; image.c syntax-table syntax-table-p
imagep
;; indent.c
current-column current-indentation
;; keyboard.c
current-idle-time current-input-mode recent-keys recursion-depth
this-command-keys this-command-keys-vector this-single-command-keys this-command-keys this-command-keys-vector this-single-command-keys
this-single-command-raw-keys this-single-command-raw-keys type-of
;; keymap.c user-real-login-name user-real-uid user-uid
current-global-map current-local-map current-minor-mode-maps keymapp vector vectorp visible-frame-list
;; minibuf.c wholenump window-configuration-p window-live-p
minibuffer-contents minibuffer-contents-no-properties minibuffer-depth window-valid-p windowp)))
minibuffer-prompt minibuffer-prompt-end
;; process.c
process-list processp signal-names waiting-for-user-input-p
;; sqlite.c
sqlite-available-p sqlitep
;; syntax.c
standard-syntax-table syntax-table syntax-table-p
;; thread.c
current-thread
;; timefns.c
current-time
;; window.c
selected-window window-configuration-p window-live-p window-valid-p
windowp
;; xdisp.c
long-line-optimizations-p
)))
(while side-effect-free-fns (while side-effect-free-fns
(put (car side-effect-free-fns) 'side-effect-free t) (put (car side-effect-free-fns) 'side-effect-free t)
(setq side-effect-free-fns (cdr side-effect-free-fns))) (setq side-effect-free-fns (cdr side-effect-free-fns)))
@ -1916,34 +1758,41 @@ See Info node `(elisp) Integer Basics'."
;; values if a marker is moved. ;; values if a marker is moved.
(let ((pure-fns (let ((pure-fns
'( '(concat regexp-quote
;; character.c string-to-char string-to-syntax symbol-name
characterp eq eql
;; data.c = /= < <= >= > min max
% * + - / /= 1+ 1- < <= = > >= aref arrayp ash atom bare-symbol + - * / % mod abs ash 1+ 1- sqrt
bool-vector-count-consecutive bool-vector-count-population logand logior lognot logxor logcount
bool-vector-p bool-vector-subsetp copysign isnan ldexp float logb
bufferp car car-safe cdr cdr-safe char-or-string-p char-table-p floor ceiling round truncate
condition-variable-p consp eq floatp integer-or-marker-p integerp ffloor fceiling fround ftruncate
keywordp listp logand logcount logior lognot logxor markerp max min string-equal string-lessp
mod multibyte-string-p mutexp natnump nlistp null number-or-marker-p string-search
numberp recordp remove-pos-from-symbol sequencep stringp symbol-name consp atom listp nlistp proper-list-p
symbolp threadp type-of vector-or-char-table-p vectorp sequencep arrayp vectorp stringp bool-vector-p hash-table-p
;; editfns.c null
string-to-char numberp integerp floatp natnump characterp
;; floatfns.c integer-or-marker-p number-or-marker-p char-or-string-p
abs ceiling copysign fceiling ffloor float floor fround ftruncate symbolp keywordp
isnan ldexp logb round sqrt truncate type-of
;; fns.c identity
assq base64-decode-string base64-encode-string base64url-encode-string
concat elt eql equal hash-table-p identity length length< length= ;; The following functions are pure up to mutation of their
length> member memq memql nth nthcdr proper-list-p rassoc rassq ;; arguments. This is pure enough for the purposes of
safe-length string-bytes string-distance string-equal string-lessp ;; constant folding, but not necessarily for all kinds of
string-search take ;; code motion.
;; search.c car cdr car-safe cdr-safe nth nthcdr take
regexp-quote equal
;; syntax.c length safe-length
string-to-syntax memq memql member
;; `assoc' and `assoc-default' are excluded since they are
;; impure if the test function is (consider `string-match').
assq rassq rassoc
aref elt
base64-decode-string base64-encode-string base64url-encode-string
bool-vector-subsetp
bool-vector-count-population bool-vector-count-consecutive
))) )))
(while pure-fns (while pure-fns
(put (car pure-fns) 'pure t) (put (car pure-fns) 'pure t)

View file

@ -145,11 +145,6 @@ So far, FUNCTION can only be a symbol, not a lambda expression."
(list 'function-put (list 'quote f) (list 'function-put (list 'quote f)
''side-effect-free (list 'quote val)))) ''side-effect-free (list 'quote val))))
(defalias 'byte-run--set-important-return-value
#'(lambda (f _args val)
(list 'function-put (list 'quote f)
''important-return-value (list 'quote val))))
(put 'compiler-macro 'edebug-declaration-spec (put 'compiler-macro 'edebug-declaration-spec
'(&or symbolp ("lambda" &define lambda-list lambda-doc def-body))) '(&or symbolp ("lambda" &define lambda-list lambda-doc def-body)))
@ -231,8 +226,6 @@ This may shift errors from run-time to compile-time.")
(list 'side-effect-free #'byte-run--set-side-effect-free (list 'side-effect-free #'byte-run--set-side-effect-free
"If non-nil, calls can be ignored if their value is unused. "If non-nil, calls can be ignored if their value is unused.
If `error-free', drop calls even if `byte-compile-delete-errors' is nil.") If `error-free', drop calls even if `byte-compile-delete-errors' is nil.")
(list 'important-return-value #'byte-run--set-important-return-value
"If non-nil, warn about calls not using the returned value.")
(list 'compiler-macro #'byte-run--set-compiler-macro) (list 'compiler-macro #'byte-run--set-compiler-macro)
(list 'doc-string #'byte-run--set-doc-string) (list 'doc-string #'byte-run--set-doc-string)
(list 'indent #'byte-run--set-indent) (list 'indent #'byte-run--set-indent)
@ -657,8 +650,11 @@ in `byte-compile-warning-types'; see the variable
`byte-compile-warnings' for a fuller explanation of the warning `byte-compile-warnings' for a fuller explanation of the warning
types. The types that can be suppressed with this macro are types. The types that can be suppressed with this macro are
`free-vars', `callargs', `redefine', `obsolete', `free-vars', `callargs', `redefine', `obsolete',
`interactive-only', `lexical', `ignored-return-value', `constants', `interactive-only', `lexical', `mapcar', `constants',
`suspicious' and `empty-body'." `suspicious' and `empty-body'.
For the `mapcar' case, only the `mapcar' function can be used in
the symbol list."
;; Note: during compilation, this definition is overridden by the one in ;; Note: during compilation, this definition is overridden by the one in
;; byte-compile-initial-macro-environment. ;; byte-compile-initial-macro-environment.
(declare (debug (sexp body)) (indent 1)) (declare (debug (sexp body)) (indent 1))

View file

@ -317,9 +317,7 @@ Elements of the list may be:
lexical-dynamic lexical-dynamic
lexically bound variable declared dynamic elsewhere lexically bound variable declared dynamic elsewhere
make-local calls to `make-variable-buffer-local' that may be incorrect. make-local calls to `make-variable-buffer-local' that may be incorrect.
ignored-return-value mapcar mapcar called for effect.
function called without using the return value where this
is likely to be a mistake
not-unused warning about using variables with symbol names starting with _. not-unused warning about using variables with symbol names starting with _.
constants let-binding of, or assignment to, constants/nonvariables. constants let-binding of, or assignment to, constants/nonvariables.
docstrings docstrings that are too wide (longer than docstrings docstrings that are too wide (longer than
@ -332,7 +330,7 @@ Elements of the list may be:
empty-body body argument to a special form or macro is empty. empty-body body argument to a special form or macro is empty.
If the list begins with `not', then the remaining elements specify warnings to If the list begins with `not', then the remaining elements specify warnings to
suppress. For example, (not free-vars) will suppress the `free-vars' warning. suppress. For example, (not mapcar) will suppress warnings about mapcar.
The t value means \"all non experimental warning types\", and The t value means \"all non experimental warning types\", and
excludes the types in `byte-compile--emacs-build-warning-types'. excludes the types in `byte-compile--emacs-build-warning-types'.
@ -3492,29 +3490,6 @@ lambda-expression."
(byte-compile-report-error (byte-compile-report-error
(format-message "`%s' defined after use in %S (missing `require' of a library file?)" (format-message "`%s' defined after use in %S (missing `require' of a library file?)"
(car form) form))) (car form) form)))
(when byte-compile--for-effect
(let ((sef (function-get (car form) 'side-effect-free)))
(cond
((and sef (or (eq sef 'error-free)
byte-compile-delete-errors))
;; This transform is normally done in the Lisp optimiser,
;; so maybe we don't need to bother about it here?
(setq form (cons 'progn (cdr form)))
(setq handler #'byte-compile-progn))
((and (or sef (function-get (car form) 'important-return-value))
;; Don't warn for arguments to `ignore'.
(not (eq byte-compile--for-effect 'for-effect-no-warn))
(byte-compile-warning-enabled-p
'ignored-return-value (car form)))
(byte-compile-warn-x
(car form)
"value from call to `%s' is unused%s"
(car form)
(cond ((eq (car form) 'mapcar)
"; use `mapc' or `dolist' instead")
(t "")))))))
(if (and handler (if (and handler
;; Make sure that function exists. ;; Make sure that function exists.
(and (functionp handler) (and (functionp handler)
@ -3538,26 +3513,6 @@ lambda-expression."
(byte-compile-discard)) (byte-compile-discard))
(pop byte-compile-form-stack))) (pop byte-compile-form-stack)))
(let ((important-return-value-fns
'(
;; These functions are side-effect-free except for the
;; behaviour of functions passed as argument.
mapcar mapcan mapconcat
assoc plist-get plist-member
;; It's safe to ignore the value of `sort' and `nreverse'
;; when used on arrays, but most calls pass lists.
nreverse sort
;; Adding these functions causes many warnings;
;; evaluate how many of them are false first.
;;delq delete
;;nconc plist-put
)))
(dolist (fn important-return-value-fns)
(put fn 'important-return-value t)))
(defun byte-compile-normal-call (form) (defun byte-compile-normal-call (form)
(when (and (symbolp (car form)) (when (and (symbolp (car form))
(byte-compile-warning-enabled-p 'callargs (car form))) (byte-compile-warning-enabled-p 'callargs (car form)))
@ -3568,7 +3523,11 @@ lambda-expression."
(byte-compile-callargs-warn form)) (byte-compile-callargs-warn form))
(if byte-compile-generate-call-tree (if byte-compile-generate-call-tree
(byte-compile-annotate-call-tree form)) (byte-compile-annotate-call-tree form))
(when (and byte-compile--for-effect (eq (car form) 'mapcar)
(byte-compile-warning-enabled-p 'mapcar 'mapcar))
(byte-compile-warn-x
(car form)
"`mapcar' called for effect; use `mapc' or `dolist' instead"))
(byte-compile-push-constant (car form)) (byte-compile-push-constant (car form))
(mapc 'byte-compile-form (cdr form)) ; wasteful, but faster. (mapc 'byte-compile-form (cdr form)) ; wasteful, but faster.
(byte-compile-out 'byte-call (length (cdr form)))) (byte-compile-out 'byte-call (length (cdr form))))
@ -4408,8 +4367,7 @@ This function is never called when `lexical-binding' is nil."
(defun byte-compile-ignore (form) (defun byte-compile-ignore (form)
(dolist (arg (cdr form)) (dolist (arg (cdr form))
;; Compile each argument for-effect but suppress unused-value warnings. (byte-compile-form arg t))
(byte-compile-form arg 'for-effect-no-warn))
(byte-compile-form nil)) (byte-compile-form nil))
;; Return the list of items in CONDITION-PARAM that match PRED-LIST. ;; Return the list of items in CONDITION-PARAM that match PRED-LIST.

View file

@ -408,7 +408,6 @@ Other non-digit chars are considered junk.
RADIX is an integer between 2 and 36, the default is 10. Signal RADIX is an integer between 2 and 36, the default is 10. Signal
an error if the substring between START and END cannot be parsed an error if the substring between START and END cannot be parsed
as an integer unless JUNK-ALLOWED is non-nil." as an integer unless JUNK-ALLOWED is non-nil."
(declare (side-effect-free t))
(cl-check-type string string) (cl-check-type string string)
(let* ((start (or start 0)) (let* ((start (or start 0))
(len (length string)) (len (length string))
@ -567,7 +566,6 @@ too large if positive or too small if negative)."
;;;###autoload ;;;###autoload
(defun cl-revappend (x y) (defun cl-revappend (x y)
"Equivalent to (append (reverse X) Y)." "Equivalent to (append (reverse X) Y)."
(declare (side-effect-free t))
(nconc (reverse x) y)) (nconc (reverse x) y))
;;;###autoload ;;;###autoload

View file

@ -459,7 +459,6 @@ Thus, `(cl-list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to
(defun cl-copy-list (list) (defun cl-copy-list (list)
"Return a copy of LIST, which may be a dotted list. "Return a copy of LIST, which may be a dotted list.
The elements of LIST are not copied, just the list structure itself." The elements of LIST are not copied, just the list structure itself."
(declare (side-effect-free error-free))
(if (consp list) (if (consp list)
(let ((res nil)) (let ((res nil))
(while (consp list) (push (pop list) res)) (while (consp list) (push (pop list) res))

View file

@ -2891,14 +2891,45 @@ The function's arguments should be treated as immutable.
,(format "compiler-macro for inlining `%s'." name) ,(format "compiler-macro for inlining `%s'." name)
(cl--defsubst-expand (cl--defsubst-expand
',argns '(cl-block ,name ,@(cdr (macroexp-parse-body body))) ',argns '(cl-block ,name ,@(cdr (macroexp-parse-body body)))
;; We used to pass `simple' as
;; (not (or unsafe (cl-expr-access-order pbody argns)))
;; But this is much too simplistic since it
;; does not pay attention to the argvs (and
;; cl-expr-access-order itself is also too naive).
nil nil
,(and (memq '&key args) 'cl-whole) nil ,@argns))) ,(and (memq '&key args) 'cl-whole) nil ,@argns)))
(cl-defun ,name ,args ,@body)))) (cl-defun ,name ,args ,@body))))
(defun cl--defsubst-expand (argns body _simple whole _unsafe &rest argvs) (defun cl--defsubst-expand (argns body simple whole _unsafe &rest argvs)
(if (and whole (not (cl--safe-expr-p (cons 'progn argvs)))) (if (and whole (not (cl--safe-expr-p (cons 'progn argvs)))) whole
whole (if (cl--simple-exprs-p argvs) (setq simple t))
`(let ,(cl-mapcar #'list argns argvs) ,body))) (let* ((substs ())
(lets (delq nil
(cl-mapcar (lambda (argn argv)
(if (or simple (macroexp-const-p argv))
(progn (push (cons argn argv) substs)
nil)
(list argn argv)))
argns argvs))))
;; FIXME: `sublis/subst' will happily substitute the symbol
;; `argn' in places where it's not used as a reference
;; to a variable.
;; FIXME: `sublis/subst' will happily copy `argv' to a different
;; scope, leading to name capture.
(setq body (cond ((null substs) body)
((null (cdr substs))
(cl-subst (cdar substs) (caar substs) body))
(t (cl--sublis substs body))))
(if lets `(let ,lets ,body) body))))
(defun cl--sublis (alist tree)
"Perform substitutions indicated by ALIST in TREE (non-destructively)."
(let ((x (assq tree alist)))
(cond
(x (cdr x))
((consp tree)
(cons (cl--sublis alist (car tree)) (cl--sublis alist (cdr tree))))
(t tree))))
;;; Structures. ;;; Structures.
@ -3213,8 +3244,19 @@ To see the documentation for a defined struct type, use
(let* ((anames (cl--arglist-args args)) (let* ((anames (cl--arglist-args args))
(make (cl-mapcar (lambda (s d) (if (memq s anames) s d)) (make (cl-mapcar (lambda (s d) (if (memq s anames) s d))
slots defaults)) slots defaults))
(con-fun (or type #'record))) ;; `cl-defsubst' is fundamentally broken: it substitutes
(push `(,cldefsym ,cname ;; its arguments into the body's `sexp' much too naively
;; when inlinling, which results in various problems.
;; For example it generates broken code if your
;; argument's name happens to be the same as some
;; function used within the body.
;; E.g. (cl-defsubst sm-foo (list) (list list))
;; will expand `(sm-foo 1)' to `(1 1)' rather than to `(list t)'!
;; Try to catch this known case!
(con-fun (or type #'record))
(unsafe-cl-defsubst
(or (memq con-fun args) (assq con-fun args))))
(push `(,(if unsafe-cl-defsubst 'cl-defun cldefsym) ,cname
(&cl-defs (nil ,@descs) ,@args) (&cl-defs (nil ,@descs) ,@args)
,(if (stringp doc) doc ,(if (stringp doc) doc
(format "Constructor for objects of type `%s'." name)) (format "Constructor for objects of type `%s'." name))
@ -3648,53 +3690,14 @@ macro that returns its `&whole' argument."
;;; Things that are side-effect-free. ;;; Things that are side-effect-free.
(mapc (lambda (x) (function-put x 'side-effect-free t)) (mapc (lambda (x) (function-put x 'side-effect-free t))
'(cl-oddp cl-evenp cl-signum cl-ldiff cl-pairlis cl-gcd '(cl-oddp cl-evenp cl-signum last butlast cl-ldiff cl-pairlis cl-gcd
cl-lcm cl-isqrt cl-floor cl-ceiling cl-truncate cl-round cl-mod cl-rem cl-lcm cl-isqrt cl-floor cl-ceiling cl-truncate cl-round cl-mod cl-rem
cl-subseq cl-list-length cl-get cl-getf)) cl-subseq cl-list-length cl-get cl-getf))
;;; Things that are side-effect-and-error-free. ;;; Things that are side-effect-and-error-free.
(mapc (lambda (x) (function-put x 'side-effect-free 'error-free)) (mapc (lambda (x) (function-put x 'side-effect-free 'error-free))
'(cl-list* cl-acons cl-equalp '(eql cl-list* cl-subst cl-acons cl-equalp
cl-random-state-p copy-tree)) cl-random-state-p copy-tree cl-sublis))
;;; Things whose return value should probably be used.
(mapc (lambda (x) (function-put x 'important-return-value t))
'(
;; Functions that are side-effect-free except for the
;; behaviour of functions passed as argument.
cl-mapcar cl-mapcan cl-maplist cl-map cl-mapcon
cl-reduce
cl-assoc cl-assoc-if cl-assoc-if-not
cl-rassoc cl-rassoc-if cl-rassoc-if-not
cl-member cl-member-if cl-member-if-not
cl-adjoin
cl-mismatch cl-search
cl-find cl-find-if cl-find-if-not
cl-position cl-position-if cl-position-if-not
cl-count cl-count-if cl-count-if-not
cl-remove cl-remove-if cl-remove-if-not
cl-remove-duplicates
cl-subst cl-subst-if cl-subst-if-not
cl-substitute cl-substitute-if cl-substitute-if-not
cl-sublis
cl-union cl-intersection cl-set-difference cl-set-exclusive-or
cl-subsetp
cl-every cl-some cl-notevery cl-notany
cl-tree-equal
;; Functions that mutate and return a list.
cl-delete cl-delete-if cl-delete-if-not
cl-delete-duplicates
cl-nsubst cl-nsubst-if cl-nsubst-if-not
cl-nsubstitute cl-nsubstitute-if cl-nsubstitute-if-not
cl-nunion cl-nintersection cl-nset-difference cl-nset-exclusive-or
cl-nreconc cl-nsublis
cl-merge
;; It's safe to ignore the value of `cl-sort' and `cl-stable-sort'
;; when used on arrays, but most calls pass lists.
cl-sort cl-stable-sort
))
;;; Types and assertions. ;;; Types and assertions.

View file

@ -176,7 +176,6 @@ supertypes from the most specific to least specific.")
(i 0) (i 0)
(offset (if type 0 1))) (offset (if type 0 1)))
(dolist (slot slots) (dolist (slot slots)
(put (car slot) 'slot-name t)
(let* ((props (cl--plist-to-alist (cddr slot))) (let* ((props (cl--plist-to-alist (cddr slot)))
(typep (assq :type props)) (typep (assq :type props))
(type (if (null typep) t (type (if (null typep) t

View file

@ -2853,7 +2853,7 @@ See `edebug-behavior-alist' for implementations.")
edebug-inside-windows edebug-inside-windows
) )
(unwind-protect
(let ( (let (
;; Declare global values local but using the same global value. ;; Declare global values local but using the same global value.
;; We could set these to the values for previous edebug call. ;; We could set these to the values for previous edebug call.
@ -2927,7 +2927,7 @@ See `edebug-behavior-alist' for implementations.")
;; gotta have a buffer to let its buffer local variables be set ;; gotta have a buffer to let its buffer local variables be set
(get-buffer-create " bogus edebug buffer")) (get-buffer-create " bogus edebug buffer"))
));; inner let ));; inner let
)) )))
;;; Display related functions ;;; Display related functions

View file

@ -681,35 +681,30 @@ This is the default value for `eldoc-documentation-strategy'."
(lambda (f) (lambda (f)
(funcall f (eldoc--make-callback :eager f))))) (funcall f (eldoc--make-callback :eager f)))))
(defun eldoc-documentation-compose () (defun eldoc--documentation-compose-1 (eagerlyp)
"Show multiple documentation strings together after waiting for all of them. "Helper function for composing multiple doc strings.
This is meant to be used as a value for `eldoc-documentation-strategy'." If EAGERLYP is non-nil show documentation as soon as possible,
(let (fns-and-callbacks) else wait for all doc strings."
;; Make all the callbacks, setting up state inside
;; `eldoc--invoke-strategy' to know how many callbacks to wait for
;; before displaying the result (bug#62816).
(run-hook-wrapped 'eldoc-documentation-functions (run-hook-wrapped 'eldoc-documentation-functions
(lambda (f) (lambda (f)
(push (cons f (eldoc--make-callback :patient f)) (let* ((callback (eldoc--make-callback
fns-and-callbacks) (if eagerlyp :eager :patient)
nil)) f))
;; Now call them. The last one will trigger the display.
(cl-loop for (f . callback) in fns-and-callbacks
for str = (funcall f callback)
when (or (null str) (stringp str)) do (funcall callback str)))
t)
(defun eldoc-documentation-compose-eagerly ()
"Show multiple documentation strings one by one as soon as possible.
This is meant to be used as a value for `eldoc-documentation-strategy'."
(run-hook-wrapped 'eldoc-documentation-functions
(lambda (f)
(let* ((callback (eldoc--make-callback :eager f))
(str (funcall f callback))) (str (funcall f callback)))
(if (or (null str) (stringp str)) (funcall callback str)) (if (or (null str) (stringp str)) (funcall callback str))
nil))) nil)))
t) t)
(defun eldoc-documentation-compose ()
"Show multiple documentation strings together after waiting for all of them.
This is meant to be used as a value for `eldoc-documentation-strategy'."
(eldoc--documentation-compose-1 nil))
(defun eldoc-documentation-compose-eagerly ()
"Show multiple documentation strings one by one as soon as possible.
This is meant to be used as a value for `eldoc-documentation-strategy'."
(eldoc--documentation-compose-1 t))
(defun eldoc-documentation-enthusiast () (defun eldoc-documentation-enthusiast ()
"Show most important documentation string produced so far. "Show most important documentation string produced so far.
This is meant to be used as a value for `eldoc-documentation-strategy'." This is meant to be used as a value for `eldoc-documentation-strategy'."

View file

@ -563,7 +563,7 @@ The same keyword arguments are supported as in
;; Emacs's Makefile sets $HOME to a nonexistent value. Needed ;; Emacs's Makefile sets $HOME to a nonexistent value. Needed
;; in batch mode only, therefore. ;; in batch mode only, therefore.
(when (and noninteractive (not (file-directory-p "~/"))) (when (and noninteractive (not (file-directory-p "~/")))
(setenv "HOME" (directory-file-name temporary-file-directory))) (setenv "HOME" temporary-file-directory))
(format "/mock::%s" temporary-file-directory)))) (format "/mock::%s" temporary-file-directory))))
"Temporary directory for remote file tests.") "Temporary directory for remote file tests.")

View file

@ -639,13 +639,6 @@ REF must have been previously obtained with `gv-ref'."
;;; Generalized variables. ;;; Generalized variables.
;; You'd think noone would write `(setf (error ...) ..)' but it
;; appears naturally as the result of macroexpansion of things like
;; (setf (pcase-exhaustive ...)).
;; We could generalize this to `throw' and `signal', but it seems
;; preferable to wait until there's a concrete need.
(gv-define-expander error (lambda (_do &rest args) `(error . ,args)))
;; Some Emacs-related place types. ;; Some Emacs-related place types.
(gv-define-simple-setter buffer-file-name set-visited-file-name t) (gv-define-simple-setter buffer-file-name set-visited-file-name t)
(make-obsolete-generalized-variable (make-obsolete-generalized-variable

View file

@ -597,7 +597,17 @@ instead of just updating them with the new/changed autoloads."
defs)))))) defs))))))
(progress-reporter-done progress)) (progress-reporter-done progress))
;; First group per output file. ;; If we have no autoloads data, but we have EXTRA-DATA, then
;; generate the (almost) empty file anyway.
(if (and (not defs) extra-data)
(with-temp-buffer
(insert (loaddefs-generate--rubric output-file nil t))
(search-backward "\f")
(insert extra-data)
(ensure-empty-lines 1)
(write-region (point-min) (point-max) output-file nil 'silent))
;; We have some data, so generate the loaddef files. First
;; group per output file.
(dolist (fdefs (seq-group-by (lambda (x) (expand-file-name (car x))) (dolist (fdefs (seq-group-by (lambda (x) (expand-file-name (car x)))
defs)) defs))
(let ((loaddefs-file (car fdefs)) (let ((loaddefs-file (car fdefs))
@ -635,12 +645,9 @@ instead of just updating them with the new/changed autoloads."
(progn (progn
(goto-char (point-max)) (goto-char (point-max))
(search-backward "\f\n" nil t)) (search-backward "\f\n" nil t))
;; Delete the old version of the section. Strictly ;; Delete the old version of the section.
;; speaking this should search for "\n\f\n;;;", but
;; there are loaddefs files in the wild that only
;; have two ';;'. (Bug#63236)
(delete-region (match-beginning 0) (delete-region (match-beginning 0)
(and (search-forward "\n\f\n;;") (and (search-forward "\n\f\n;;;")
(match-beginning 0))) (match-beginning 0)))
(forward-line -2))) (forward-line -2)))
(insert head) (insert head)
@ -656,7 +663,7 @@ instead of just updating them with the new/changed autoloads."
(write-region (point-min) (point-max) loaddefs-file nil 'silent) (write-region (point-min) (point-max) loaddefs-file nil 'silent)
(byte-compile-info (byte-compile-info
(file-relative-name loaddefs-file (car (ensure-list dir))) (file-relative-name loaddefs-file (car (ensure-list dir)))
t "GEN"))))))) t "GEN"))))))))
(defun loaddefs-generate--print-form (def) (defun loaddefs-generate--print-form (def)
"Print DEF in a format that makes sense for version control." "Print DEF in a format that makes sense for version control."

View file

@ -24,7 +24,7 @@
;; While packages managed by package.el use tarballs for distributing ;; While packages managed by package.el use tarballs for distributing
;; the source code, this extension allows for packages to be fetched ;; the source code, this extension allows for packages to be fetched
;; and upgraded directly from a version control system. ;; and updated directly from a version control system.
;; ;;
;; To install a package from source use `package-vc-install'. If you ;; To install a package from source use `package-vc-install'. If you
;; aren't interested in activating a package, you can use ;; aren't interested in activating a package, you can use
@ -147,9 +147,32 @@ is a symbol designating the package and SPEC is one of:
- nil, if any package version can be installed; - nil, if any package version can be installed;
- a version string, if that specific revision is to be installed; - a version string, if that specific revision is to be installed;
- a property list, describing a package specification. For more - a property list, describing a package specification. Valid
details, please consult the subsection \"Specifying Package key/value pairs are
Sources\" in the Info node `(emacs)Fetching Package Sources'.
`:url' (string)
The URL of the repository used to fetch the package source.
`:branch' (string)
If given, the name of the branch to checkout after cloning the directory.
`:lisp-dir' (string)
The repository-relative name of the directory to use for loading the Lisp
sources. If not given, the value defaults to the root directory
of the repository.
`:main-file' (string)
The main file of the project, relevant to gather package metadata.
If not given, the assumed default is the package name with \".el\"
appended to it.
`:vc-backend' (symbol)
A symbol of the VC backend to use for cloning the package. The
value ought to be a member of `vc-handled-backends'. If omitted,
`vc-clone' will fall back onto the archive default or on
`package-vc-default-backend'.
All other keys are ignored.
This user option will be automatically updated to store package This user option will be automatically updated to store package
specifications for packages that are not specified in any specifications for packages that are not specified in any
@ -163,11 +186,10 @@ archive."
(:branch string) (:branch string)
(:lisp-dir string) (:lisp-dir string)
(:main-file string) (:main-file string)
(:doc string)
(:vc-backend symbol))))) (:vc-backend symbol)))))
:version "29.1") :version "29.1")
(defvar package-vc--archive-spec-alists nil (defvar package-vc--archive-spec-alist nil
"List of package specifications for each archive. "List of package specifications for each archive.
The list maps each package name, as a string, to a plist as The list maps each package name, as a string, to a plist as
specified in `package-vc-selected-packages'.") specified in `package-vc-selected-packages'.")
@ -199,15 +221,15 @@ name for PKG-DESC."
(not (alist-get name package-vc-selected-packages (not (alist-get name package-vc-selected-packages
nil nil #'string=))) nil nil #'string=)))
(alist-get (intern (package-desc-archive pkg-desc)) (alist-get (intern (package-desc-archive pkg-desc))
package-vc--archive-spec-alists) package-vc--archive-spec-alist)
;; Consult both our local list of package specifications, as well ;; Consult both our local list of package specifications, as well
;; as the lists provided by the archives. ;; as the lists provided by the archives.
(apply #'append (cons package-vc-selected-packages (apply #'append (cons package-vc-selected-packages
(mapcar #'cdr package-vc--archive-spec-alists)))) (mapcar #'cdr package-vc--archive-spec-alist))))
'() nil #'string=)) '() nil #'string=))
(defun package-vc--read-archive-data (archive) (defun package-vc--read-archive-data (archive)
"Update `package-vc--archive-spec-alists' for ARCHIVE. "Update `package-vc--archive-spec-alist' for ARCHIVE.
This function is meant to be used as a hook for `package-read-archive-hook'." This function is meant to be used as a hook for `package-read-archive-hook'."
(let ((contents-file (expand-file-name (let ((contents-file (expand-file-name
(format "archives/%s/elpa-packages.eld" archive) (format "archives/%s/elpa-packages.eld" archive)
@ -224,7 +246,7 @@ This function is meant to be used as a hook for `package-read-archive-hook'."
(let ((spec (read (current-buffer)))) (let ((spec (read (current-buffer))))
(when (eq package-vc--elpa-packages-version (when (eq package-vc--elpa-packages-version
(plist-get (cdr spec) :version)) (plist-get (cdr spec) :version))
(setf (alist-get (intern archive) package-vc--archive-spec-alists) (setf (alist-get (intern archive) package-vc--archive-spec-alist)
(car spec))) (car spec)))
(setf (alist-get (intern archive) package-vc--archive-data-alist) (setf (alist-get (intern archive) package-vc--archive-data-alist)
(cdr spec)) (cdr spec))
@ -235,7 +257,7 @@ This function is meant to be used as a hook for `package-read-archive-hook'."
(defun package-vc--download-and-read-archives (&optional async) (defun package-vc--download-and-read-archives (&optional async)
"Download specifications of all `package-archives' and read them. "Download specifications of all `package-archives' and read them.
Populate `package-vc--archive-spec-alists' with the result. Populate `package-vc--archive-spec-alist' with the result.
If optional argument ASYNC is non-nil, perform the downloads If optional argument ASYNC is non-nil, perform the downloads
asynchronously." asynchronously."
@ -583,7 +605,7 @@ Emacs Lisp files.")
(defun package-vc--unpack (pkg-desc pkg-spec &optional rev) (defun package-vc--unpack (pkg-desc pkg-spec &optional rev)
"Install the package described by PKG-DESC. "Install the package described by PKG-DESC.
PKG-SPEC is a package specification, a property list describing PKG-SPEC is a package specification, a property list describing
how to fetch and build the package. See `package-vc--archive-spec-alists' how to fetch and build the package. See `package-vc--archive-spec-alist'
for details. The optional argument REV specifies a specific revision to for details. The optional argument REV specifies a specific revision to
checkout. This overrides the `:branch' attribute in PKG-SPEC." checkout. This overrides the `:branch' attribute in PKG-SPEC."
(unless (eq (package-desc-kind pkg-desc) 'vc) (unless (eq (package-desc-kind pkg-desc) 'vc)
@ -632,8 +654,7 @@ abort installation?" name))
(throw 'done (setq lisp-dir name))))) (throw 'done (setq lisp-dir name)))))
;; Ensure we have a copy of the package specification ;; Ensure we have a copy of the package specification
(unless (seq-some (lambda (alist) (equal (alist-get name (cdr alist)) pkg-spec)) (unless (equal (alist-get name (mapcar #'cdr package-vc--archive-spec-alist)) pkg-spec)
package-vc--archive-spec-alists)
(customize-save-variable (customize-save-variable
'package-vc-selected-packages 'package-vc-selected-packages
(cons (cons name pkg-spec) (cons (cons name pkg-spec)
@ -673,19 +694,19 @@ installed package."
#'string=))) #'string=)))
;;;###autoload ;;;###autoload
(defun package-vc-upgrade-all () (defun package-vc-update-all ()
"Attempt to upgrade all installed VC packages." "Attempt to update all installed VC packages."
(interactive) (interactive)
(dolist (package package-alist) (dolist (package package-alist)
(dolist (pkg-desc (cdr package)) (dolist (pkg-desc (cdr package))
(when (package-vc-p pkg-desc) (when (package-vc-p pkg-desc)
(package-vc-upgrade pkg-desc)))) (package-vc-update pkg-desc))))
(message "Done upgrading packages.")) (message "Done updating packages."))
;;;###autoload ;;;###autoload
(defun package-vc-upgrade (pkg-desc) (defun package-vc-update (pkg-desc)
"Attempt to upgrade the package PKG-DESC." "Attempt to update the package PKG-DESC."
(interactive (list (package-vc--read-package-desc "Upgrade VC package: " t))) (interactive (list (package-vc--read-package-desc "Update VC package: " t)))
;; HACK: To run `package-vc--unpack-1' after checking out the new ;; HACK: To run `package-vc--unpack-1' after checking out the new
;; revision, we insert a hook into `vc-post-command-functions', and ;; revision, we insert a hook into `vc-post-command-functions', and
;; remove it right after it ran. To avoid running the hook multiple ;; remove it right after it ran. To avoid running the hook multiple
@ -883,7 +904,7 @@ Rebuilding an installation means scraping for new autoload
cookies, re-compiling Emacs Lisp files, building and installing cookies, re-compiling Emacs Lisp files, building and installing
any documentation, downloading any missing dependencies. This any documentation, downloading any missing dependencies. This
command does not fetch new revisions from a remote server. That command does not fetch new revisions from a remote server. That
is the responsibility of `package-vc-upgrade'. Interactively, is the responsibility of `package-vc-update'. Interactively,
prompt for the name of the package to rebuild." prompt for the name of the package to rebuild."
(interactive (list (package-vc--read-package-desc "Rebuild package: " t))) (interactive (list (package-vc--read-package-desc "Rebuild package: " t)))
(package-vc--unpack-1 pkg-desc (package-desc-dir pkg-desc))) (package-vc--unpack-1 pkg-desc (package-desc-dir pkg-desc)))

View file

@ -795,21 +795,6 @@ specifying the minimum acceptable version."
(require 'finder-inf nil t) ; For `package--builtins'. (require 'finder-inf nil t) ; For `package--builtins'.
(assq package package--builtins)))))) (assq package package--builtins))))))
(defun package--active-built-in-p (package)
"Return non-nil if the built-in version of PACKAGE is used.
If the built-in version of PACKAGE is used and PACKAGE is
also available for installation from an archive, it is an
indication that PACKAGE was never upgraded to any newer
version from the archive."
(and (not (assq (cond
((package-desc-p package)
(package-desc-name package))
((stringp package) (intern package))
((symbolp package) package)
((error "Unknown package format: %S" package)))
(package--alist)))
(package-built-in-p package)))
(defun package--autoloads-file-name (pkg-desc) (defun package--autoloads-file-name (pkg-desc)
"Return the absolute name of the autoloads file, sans extension. "Return the absolute name of the autoloads file, sans extension.
PKG-DESC is a `package-desc' object." PKG-DESC is a `package-desc' object."
@ -1196,7 +1181,7 @@ boundaries."
;; the earliest in version 31.1. The idea is to phase out the ;; the earliest in version 31.1. The idea is to phase out the
;; requirement for a "footer line" without unduly impacting users ;; requirement for a "footer line" without unduly impacting users
;; on earlier Emacs versions. See Bug#26490 for more details. ;; on earlier Emacs versions. See Bug#26490 for more details.
(unless (search-forward (concat ";;; " file-name ".el ends here") nil t) (unless (search-forward (concat ";;; " file-name ".el ends here"))
(lwarn '(package package-format) :warning (lwarn '(package package-format) :warning
"Package lacks a terminating comment")) "Package lacks a terminating comment"))
;; Try to include a trailing newline. ;; Try to include a trailing newline.
@ -1224,8 +1209,8 @@ boundaries."
:url website :url website
:keywords keywords :keywords keywords
:maintainer :maintainer
;; For backward compatibility, use a single cons-cell if ;; For backward compatibility, use a single string if there's only
;; there's only one maintainer (the most common case). ;; one maintainer (the most common case).
(let ((maints (lm-maintainers))) (if (cdr maints) maints (car maints))) (let ((maints (lm-maintainers))) (if (cdr maints) maints (car maints)))
:authors (lm-authors))))) :authors (lm-authors)))))
@ -1233,6 +1218,7 @@ boundaries."
"Read a `define-package' form in current buffer. "Read a `define-package' form in current buffer.
Return the pkg-desc, with desc-kind set to KIND." Return the pkg-desc, with desc-kind set to KIND."
(goto-char (point-min)) (goto-char (point-min))
(unwind-protect
(let* ((pkg-def-parsed (read (current-buffer))) (let* ((pkg-def-parsed (read (current-buffer)))
(pkg-desc (pkg-desc
(when (eq (car pkg-def-parsed) 'define-package) (when (eq (car pkg-def-parsed) 'define-package)
@ -1240,7 +1226,7 @@ Return the pkg-desc, with desc-kind set to KIND."
(append (cdr pkg-def-parsed)))))) (append (cdr pkg-def-parsed))))))
(when pkg-desc (when pkg-desc
(setf (package-desc-kind pkg-desc) kind) (setf (package-desc-kind pkg-desc) kind)
pkg-desc))) pkg-desc))))
(declare-function tar-get-file-descriptor "tar-mode" (file)) (declare-function tar-get-file-descriptor "tar-mode" (file))
(declare-function tar--extract "tar-mode" (descriptor)) (declare-function tar--extract "tar-mode" (descriptor))
@ -2193,18 +2179,12 @@ using `package-compute-transaction'."
(unless package-archive-contents (unless package-archive-contents
(package-refresh-contents))) (package-refresh-contents)))
(defcustom package-install-upgrade-built-in nil
"Non-nil means that built-in packages can be upgraded via a package archive.
If disabled, then `package-install' will not suggest to replace a
built-in package with a (possibly newer) version from a package archive."
:type 'boolean
:version "29.1")
;;;###autoload ;;;###autoload
(defun package-install (pkg &optional dont-select) (defun package-install (pkg &optional dont-select)
"Install the package PKG. "Install the package PKG.
PKG can be a `package-desc' or a symbol naming one of the PKG can be a `package-desc' or a symbol naming one of the
available packages in an archive in `package-archives'. available packages in an archive in `package-archives'. When
called interactively, prompt for the package name.
Mark the installed package as selected by adding it to Mark the installed package as selected by adding it to
`package-selected-packages'. `package-selected-packages'.
@ -2214,11 +2194,7 @@ non-nil, install the package but do not add it to
`package-selected-packages'. `package-selected-packages'.
If PKG is a `package-desc' and it is already installed, don't try If PKG is a `package-desc' and it is already installed, don't try
to install it but still mark it as selected. to install it but still mark it as selected."
If the command is invoked with a prefix argument, it will allow
upgrading of built-in packages, as if `package-install-upgrade-built-in'
had been enabled."
(interactive (interactive
(progn (progn
;; Initialize the package system to get the list of package ;; Initialize the package system to get the list of package
@ -2226,14 +2202,11 @@ had been enabled."
(package--archives-initialize) (package--archives-initialize)
(list (intern (completing-read (list (intern (completing-read
"Install package: " "Install package: "
(mapcan (delq nil
(lambda (elt) (mapcar (lambda (elt)
(and (or (and (or current-prefix-arg (unless (package-installed-p (car elt))
package-install-upgrade-built-in) (symbol-name (car elt))))
(package--active-built-in-p (car elt))) package-archive-contents))
(not (package-installed-p (car elt))))
(list (symbol-name (car elt)))))
package-archive-contents)
nil t)) nil t))
nil))) nil)))
(package--archives-initialize) (package--archives-initialize)
@ -2244,9 +2217,6 @@ had been enabled."
(unless (or dont-select (package--user-selected-p name)) (unless (or dont-select (package--user-selected-p name))
(package--save-selected-packages (package--save-selected-packages
(cons name package-selected-packages))) (cons name package-selected-packages)))
(when (and (or current-prefix-arg package-install-upgrade-built-in)
(package--active-built-in-p pkg))
(setq pkg (or (cadr (assq name package-archive-contents)) pkg)))
(if-let* ((transaction (if-let* ((transaction
(if (package-desc-p pkg) (if (package-desc-p pkg)
(unless (package-installed-p pkg) (unless (package-installed-p pkg)
@ -2259,30 +2229,24 @@ had been enabled."
(message "Package `%s' installed." name)) (message "Package `%s' installed." name))
(message "`%s' is already installed" name)))) (message "`%s' is already installed" name))))
(declare-function package-vc-upgrade "package-vc" (pkg)) (declare-function package-vc-update "package-vc" (pkg))
;;;###autoload ;;;###autoload
(defun package-upgrade (name) (defun package-update (name)
"Upgrade package NAME if a newer version exists." "Update package NAME if a newer version exists."
(interactive (interactive
(list (completing-read (list (completing-read
"Upgrade package: " (package--upgradeable-packages t) nil t))) "Update package: " (package--updateable-packages) nil t)))
(let* ((package (if (symbolp name) (let* ((package (if (symbolp name)
name name
(intern name))) (intern name)))
(pkg-desc (cadr (assq package package-alist))) (pkg-desc (cadr (assq package package-alist))))
(package-install-upgrade-built-in (not pkg-desc))) (if (package-vc-p pkg-desc)
;; `pkg-desc' will be nil when the package is an "active built-in". (package-vc-update pkg-desc)
(if (and pkg-desc (package-vc-p pkg-desc)) (package-delete pkg-desc 'force)
(package-vc-upgrade pkg-desc) (package-install package 'dont-select))))
(when pkg-desc
(package-delete pkg-desc 'force 'dont-unselect))
(package-install package
;; An active built-in has never been "selected"
;; before. Mark it as installed explicitly.
(and pkg-desc 'dont-select)))))
(defun package--upgradeable-packages (&optional include-builtins) (defun package--updateable-packages ()
;; Initialize the package system to get the list of package ;; Initialize the package system to get the list of package
;; symbols for completion. ;; symbols for completion.
(package--archives-initialize) (package--archives-initialize)
@ -2293,46 +2257,30 @@ had been enabled."
(or (let ((available (or (let ((available
(assq (car elt) package-archive-contents))) (assq (car elt) package-archive-contents)))
(and available (and available
(or (and
include-builtins
(not (package-desc-version (cadr elt))))
(version-list-< (version-list-<
(package-desc-version (cadr elt)) (package-desc-version (cadr elt))
(package-desc-version (cadr available)))))) (package-desc-version (cadr available)))))
(package-vc-p (cadr elt)))) (package-vc-p (cadr (assq (car elt) package-alist)))))
(if include-builtins package-alist)))
(append package-alist
(mapcan
(lambda (elt)
(when (not (assq (car elt) package-alist))
(list (list (car elt) (package--from-builtin elt)))))
package--builtins))
package-alist))))
;;;###autoload ;;;###autoload
(defun package-upgrade-all (&optional query) (defun package-update-all (&optional query)
"Refresh package list and upgrade all packages. "Refresh package list and upgrade all packages.
If QUERY, ask the user before upgrading packages. When called If QUERY, ask the user before updating packages. When called
interactively, QUERY is always true. interactively, QUERY is always true."
Currently, packages which are part of the Emacs distribution are
not upgraded by this command. To enable upgrading such a package
using this command, first upgrade the package to a newer version
from ELPA by either using `\\[package-upgrade]' or
`\\<package-menu-mode-map>\\[package-menu-mark-install]' after `\\[list-packages]'."
(interactive (list (not noninteractive))) (interactive (list (not noninteractive)))
(package-refresh-contents) (package-refresh-contents)
(let ((upgradeable (package--upgradeable-packages))) (let ((updateable (package--updateable-packages)))
(if (not upgradeable) (if (not updateable)
(message "No packages to upgrade") (message "No packages to update")
(when (and query (when (and query
(not (yes-or-no-p (not (yes-or-no-p
(if (length= upgradeable 1) (if (length= updateable 1)
"One package to upgrade. Do it? " "One package to update. Do it? "
(format "%s packages to upgrade. Do it?" (format "%s packages to update. Do it?"
(length upgradeable)))))) (length updateable))))))
(user-error "Upgrade aborted")) (user-error "Updating aborted"))
(mapc #'package-upgrade upgradeable)))) (mapc #'package-update updateable))))
(defun package--dependencies (pkg) (defun package--dependencies (pkg)
"Return a list of all dependencies PKG has. "Return a list of all dependencies PKG has.
@ -2745,8 +2693,7 @@ Helper function for `describe-package'."
(status (if desc (package-desc-status desc) "orphan")) (status (if desc (package-desc-status desc) "orphan"))
(incompatible-reason (package--incompatible-p desc)) (incompatible-reason (package--incompatible-p desc))
(signed (if desc (package-desc-signed desc))) (signed (if desc (package-desc-signed desc)))
(maintainers (or (cdr (assoc :maintainers extras)) (maintainer (cdr (assoc :maintainer extras)))
(cdr (assoc :maintainer extras))))
(authors (cdr (assoc :authors extras))) (authors (cdr (assoc :authors extras)))
(news (and-let* (pkg-dir (news (and-let* (pkg-dir
((not built-in)) ((not built-in))
@ -2881,21 +2828,19 @@ Helper function for `describe-package'."
'action 'package-keyword-button-action) 'action 'package-keyword-button-action)
(insert " ")) (insert " "))
(insert "\n")) (insert "\n"))
(when maintainers (when maintainer
(unless (proper-list-p maintainers) (package--print-help-section "Maintainer")
(setq maintainers (list maintainers))) (package--print-email-button maintainer))
(package--print-help-section
(if (cdr maintainers) "Maintainers" "Maintainer"))
(dolist (maintainer maintainers)
(when (bolp)
(insert (make-string 13 ?\s)))
(package--print-email-button maintainer)))
(when authors (when authors
(package--print-help-section (if (cdr authors) "Authors" "Author")) (package--print-help-section
(dolist (author authors) (if (= (length authors) 1)
(when (bolp) "Author"
(insert (make-string 13 ?\s))) "Authors"))
(package--print-email-button author))) (package--print-email-button (pop authors))
;; If there's more than one author, indent the rest correctly.
(dolist (name authors)
(insert (make-string 13 ?\s))
(package--print-email-button name)))
(let* ((all-pkgs (append (cdr (assq name package-alist)) (let* ((all-pkgs (append (cdr (assq name package-alist))
(cdr (assq name package-archive-contents)) (cdr (assq name package-archive-contents))
(let ((bi (assq name package--builtins))) (let ((bi (assq name package--builtins)))

View file

@ -722,12 +722,16 @@ Vi's prefix argument will be used. Otherwise, the prefix argument passed to
(let (viper-vi-kbd-minor-mode (let (viper-vi-kbd-minor-mode
viper-insert-kbd-minor-mode viper-insert-kbd-minor-mode
viper-emacs-kbd-minor-mode) viper-emacs-kbd-minor-mode)
(setq com (key-binding (setq key (read-key-sequence nil)))) (unwind-protect
(progn
(setq com
(key-binding (setq key (read-key-sequence nil))))
;; In case of binding indirection--chase definitions. ;; In case of binding indirection--chase definitions.
;; Have to do it here because we execute this command under ;; Have to do it here because we execute this command under
;; different keymaps, so command-execute may not do the ;; different keymaps, so command-execute may not do the
;; right thing there ;; right thing there
(while (vectorp com) (setq com (key-binding com))) (while (vectorp com) (setq com (key-binding com))))
nil)
;; Execute command com in the original Viper state, not in state ;; Execute command com in the original Viper state, not in state
;; `state'. Otherwise, if we switch buffers while executing the ;; `state'. Otherwise, if we switch buffers while executing the
;; escaped to command, Viper's mode vars will remain those of ;; escaped to command, Viper's mode vars will remain those of
@ -1946,7 +1950,7 @@ To turn this feature off, set this variable to nil."
(if found (if found
() ()
(viper-tmp-insert-at-eob " [Please complete file name]") (viper-tmp-insert-at-eob " [Please complete file name]")
(unwind-protect
(while (not (memq cmd (while (not (memq cmd
'(exit-minibuffer viper-exit-minibuffer))) '(exit-minibuffer viper-exit-minibuffer)))
(setq cmd (setq cmd
@ -1955,7 +1959,7 @@ To turn this feature off, set this variable to nil."
(insert key)) (insert key))
((memq cmd '(exit-minibuffer viper-exit-minibuffer)) ((memq cmd '(exit-minibuffer viper-exit-minibuffer))
nil) nil)
(t (command-execute cmd))))))))) (t (command-execute cmd))))))))))
(defun viper-minibuffer-trim-tail () (defun viper-minibuffer-trim-tail ()

View file

@ -294,8 +294,7 @@
"\\|" "\\|"
"bash$\\|bash.exe$" "bash$\\|bash.exe$"
"\\)") "\\)")
shell-file-name) shell-file-name)))
t))
"Is the user using a unix-type shell under a non-OS?" "Is the user using a unix-type shell under a non-OS?"
:type 'boolean) :type 'boolean)

View file

@ -47,8 +47,7 @@
(defun viper-window-display-p () (defun viper-window-display-p ()
(and window-system (not (memq window-system '(tty stream pc))))) (and window-system (not (memq window-system '(tty stream pc)))))
(defcustom viper-ms-style-os-p (defcustom viper-ms-style-os-p (memq system-type '(ms-dos windows-nt))
(not (not (memq system-type '(ms-dos windows-nt))))
"Non-nil if Emacs is running under an MS-style OS: MS-DOS, or MS-Windows." "Non-nil if Emacs is running under an MS-style OS: MS-DOS, or MS-Windows."
:type 'boolean :type 'boolean
:tag "Is it Microsoft-made OS?" :tag "Is it Microsoft-made OS?"

View file

@ -102,12 +102,11 @@
(require 'erc-common) (require 'erc-common)
(defvar erc--target) (defvar erc--target)
(defvar erc--user-from-nick-function) (defvar erc-auto-query)
(defvar erc-channel-list) (defvar erc-channel-list)
(defvar erc-channel-users) (defvar erc-channel-users)
(defvar erc-default-nicks) (defvar erc-default-nicks)
(defvar erc-default-recipients) (defvar erc-default-recipients)
(defvar erc-ensure-target-buffer-on-privmsg)
(defvar erc-format-nick-function) (defvar erc-format-nick-function)
(defvar erc-format-query-as-channel-p) (defvar erc-format-query-as-channel-p)
(defvar erc-hide-prompt) (defvar erc-hide-prompt)
@ -124,8 +123,6 @@
(defvar erc-nick-change-attempt-count) (defvar erc-nick-change-attempt-count)
(defvar erc-prompt-for-channel-key) (defvar erc-prompt-for-channel-key)
(defvar erc-prompt-hidden) (defvar erc-prompt-hidden)
(defvar erc-receive-query-display)
(defvar erc-receive-query-display-defer)
(defvar erc-reuse-buffers) (defvar erc-reuse-buffers)
(defvar erc-verbose-server-ping) (defvar erc-verbose-server-ping)
(defvar erc-whowas-on-nosuchnick) (defvar erc-whowas-on-nosuchnick)
@ -300,12 +297,6 @@ function `erc-server-process-alive' instead.")
(defvar-local erc-server-reconnect-count 0 (defvar-local erc-server-reconnect-count 0
"Number of times we have failed to reconnect to the current server.") "Number of times we have failed to reconnect to the current server.")
(defvar-local erc--server-reconnect-display-timer nil
"Timer that resets `erc--server-last-reconnect-count' to zero.
Becomes non-nil in all server buffers when an IRC connection is
first \"established\" and carries out its duties
`erc-reconnect-display-timeout' seconds later.")
(defvar-local erc--server-last-reconnect-count 0 (defvar-local erc--server-last-reconnect-count 0
"Snapshot of reconnect count when the connection was established.") "Snapshot of reconnect count when the connection was established.")
@ -424,12 +415,8 @@ This only has an effect if `erc-server-auto-reconnect' is non-nil."
(defcustom erc-server-reconnect-timeout 1 (defcustom erc-server-reconnect-timeout 1
"Number of seconds to wait between successive reconnect attempts. "Number of seconds to wait between successive reconnect attempts.
If this value is too low, servers may reject your initial nick
request upon reconnecting because they haven't yet noticed that If a key is pressed while ERC is waiting, it will stop waiting."
your previous connection is dead. If this happens, try setting
this value to 120 or greater and/or exploring the option
`erc-nickname-in-use-functions', which may provide a more
proactive means of handling this situation on some servers."
:type 'number) :type 'number)
(defcustom erc-server-reconnect-function 'erc-server-delayed-reconnect (defcustom erc-server-reconnect-function 'erc-server-delayed-reconnect
@ -440,7 +427,6 @@ dialing. Use `erc-schedule-reconnect' to instead try again later
and optionally alter the attempts tally." and optionally alter the attempts tally."
:package-version '(ERC . "5.5") :package-version '(ERC . "5.5")
:type '(choice (function-item erc-server-delayed-reconnect) :type '(choice (function-item erc-server-delayed-reconnect)
(function-item erc-server-delayed-check-reconnect)
function)) function))
(defcustom erc-split-line-length 440 (defcustom erc-split-line-length 440
@ -573,47 +559,6 @@ If this is set to nil, never try to reconnect."
;;;; Helper functions ;;;; Helper functions
(defvar erc--reject-unbreakable-lines nil
"Signal an error when a line exceeds `erc-split-line-length'.
Sending such lines and hoping for the best is no longer supported
in ERC 5.6. This internal var exists as a possibly temporary
escape hatch for inhibiting their transmission.")
(defun erc--split-line (longline)
(let* ((coding (erc-coding-system-for-target nil))
(original-window-buf (window-buffer (selected-window)))
out)
(when (consp coding)
(setq coding (car coding)))
(setq coding (coding-system-change-eol-conversion coding 'unix))
(unwind-protect
(with-temp-buffer
(set-window-buffer (selected-window) (current-buffer))
(insert longline)
(goto-char (point-min))
(while (not (eobp))
(let ((upper (filepos-to-bufferpos erc-split-line-length
'exact coding)))
(goto-char (or upper (point-max)))
(unless (eobp)
(skip-chars-backward "^ \t"))
(when (bobp)
(when erc--reject-unbreakable-lines
(user-error
(substitute-command-keys
(concat "Unbreakable line encountered "
"(Recover input with \\[erc-previous-command])"))))
(goto-char upper))
(when-let ((cmp (find-composition (point) (1+ (point)))))
(if (= (car cmp) (point-min))
(goto-char (nth 1 cmp))
(goto-char (car cmp)))))
(cl-assert (/= (point-min) (point)))
(push (buffer-substring-no-properties (point-min) (point)) out)
(delete-region (point-min) (point)))
(or (nreverse out) (list "")))
(set-window-buffer (selected-window) original-window-buf))))
;; From Circe ;; From Circe
(defun erc-split-line (longline) (defun erc-split-line (longline)
"Return a list of lines which are not too long for IRC. "Return a list of lines which are not too long for IRC.
@ -713,30 +658,6 @@ The current buffer is given by BUFFER."
(run-hooks 'erc--server-post-connect-hook) (run-hooks 'erc--server-post-connect-hook)
(erc-login)) (erc-login))
(defvar erc--server-connect-function #'erc--server-propagate-failed-connection
"Function called one second after creating a server process.
Called with the newly created process just before the opening IRC
protocol exchange.")
(defun erc--server-propagate-failed-connection (process)
"Ensure the PROCESS sentinel runs at least once on early failure.
Act as a watchdog timer to force `erc-process-sentinel' and its
finalizers, like `erc-disconnected-hook', to run when PROCESS has
a status of `failed' after one second. But only do so when its
error data is something ERC recognizes. Print an explanation to
the server buffer in any case."
(when (eq (process-status process) 'failed)
(erc-display-message
nil 'error (process-buffer process)
(format "Process exit status: %S" (process-exit-status process)))
(pcase (process-exit-status process)
(111
(erc-process-sentinel process "failed with code 111\n"))
(`(file-error . ,_)
(erc-process-sentinel process "failed with code -523\n"))
((rx "tls" (+ nonl) "failed")
(erc-process-sentinel process "failed with code -525\n")))))
(defvar erc--server-connect-dumb-ipv6-regexp (defvar erc--server-connect-dumb-ipv6-regexp
;; Not for validation (gives false positives). ;; Not for validation (gives false positives).
(rx bot "[" (group (+ (any xdigit digit ":.")) (? "%" (+ alnum))) "]" eot)) (rx bot "[" (group (+ (any xdigit digit ":.")) (? "%" (+ alnum))) "]" eot))
@ -789,9 +710,7 @@ TLS (see `erc-session-client-certificate' for more details)."
;; MOTD line) ;; MOTD line)
(if (eq (process-status process) 'connect) (if (eq (process-status process) 'connect)
;; waiting for a non-blocking connect - keep the user informed ;; waiting for a non-blocking connect - keep the user informed
(progn
(erc-display-message nil nil buffer "Opening connection..\n") (erc-display-message nil nil buffer "Opening connection..\n")
(run-at-time 1 nil erc--server-connect-function process))
(message "%s...done" msg) (message "%s...done" msg)
(erc--register-connection)))) (erc--register-connection))))
@ -825,78 +744,6 @@ Make sure you are in an ERC buffer when running this."
(with-current-buffer buffer (with-current-buffer buffer
(erc-server-reconnect)))) (erc-server-reconnect))))
(defvar-local erc--server-reconnect-timeout nil)
(defvar-local erc--server-reconnect-timeout-check 10)
(defvar-local erc--server-reconnect-timeout-scale-function
#'erc--server-reconnect-timeout-double)
(defun erc--server-reconnect-timeout-double (existing)
"Double EXISTING timeout, but cap it at 5 minutes."
(min 300 (* existing 2)))
;; This may appear to hang at various places. It's assumed that when
;; *Messages* contains "Waiting for socket ..." or similar, progress
;; will be made eventually.
(defun erc-server-delayed-check-reconnect (buffer)
"Wait for internet connectivity before trying to reconnect.
Expect BUFFER to be the server buffer for the current connection."
(when (buffer-live-p buffer)
(with-current-buffer buffer
(setq erc--server-reconnect-timeout
(funcall erc--server-reconnect-timeout-scale-function
(or erc--server-reconnect-timeout
erc-server-reconnect-timeout)))
(let* ((reschedule (lambda (proc)
(when (buffer-live-p buffer)
(with-current-buffer buffer
(let ((erc-server-reconnect-timeout
erc--server-reconnect-timeout))
(delete-process proc)
(erc-display-message nil 'error buffer
"Nobody home...")
(erc-schedule-reconnect buffer 0))))))
(conchk-exp (time-add erc--server-reconnect-timeout-check
(current-time)))
(conchk-timer nil)
(conchk (lambda (proc)
(let ((status (process-status proc))
(xprdp (time-less-p conchk-exp (current-time))))
(when (or (not (eq 'connect status)) xprdp)
(cancel-timer conchk-timer))
(when (buffer-live-p buffer)
(cond (xprdp (erc-display-message
nil 'error buffer
"Timed out while dialing...")
(delete-process proc)
(funcall reschedule proc))
((eq 'failed status)
(funcall reschedule proc)))))))
(sentinel (lambda (proc event)
(pcase event
("open\n"
(run-at-time nil nil #'send-string proc
(format "PING %d\r\n"
(time-convert nil 'integer))))
((or "connection broken by remote peer\n"
(rx bot "failed"))
(funcall reschedule proc)))))
(filter (lambda (proc _)
(delete-process proc)
(with-current-buffer buffer
(setq erc--server-reconnect-timeout nil))
(run-at-time nil nil #'erc-server-delayed-reconnect
buffer))))
(condition-case _
(let ((proc (funcall erc-session-connector
"*erc-connectivity-check*" nil
erc-session-server erc-session-port
:nowait t)))
(setq conchk-timer (run-at-time 1 1 conchk proc))
(set-process-filter proc filter)
(set-process-sentinel proc sentinel))
(file-error (funcall reschedule nil)))))))
(defun erc-server-filter-function (process string) (defun erc-server-filter-function (process string)
"The process filter for the ERC server." "The process filter for the ERC server."
(with-current-buffer (process-buffer process) (with-current-buffer (process-buffer process)
@ -951,22 +798,6 @@ EVENT is the message received from the closed connection process."
erc-server-reconnecting) erc-server-reconnecting)
(erc--server-reconnect-p event))) (erc--server-reconnect-p event)))
(defun erc--server-last-reconnect-on-disconnect (&rest _)
(remove-hook 'erc-disconnected-hook
#'erc--server-last-reconnect-on-disconnect t)
(erc--server-last-reconnect-display-reset (current-buffer)))
(defun erc--server-last-reconnect-display-reset (buffer)
"Deactivate `erc-reconnect-display'."
(when (buffer-live-p buffer)
(with-current-buffer buffer
(when erc--server-reconnect-display-timer
(cancel-timer erc--server-reconnect-display-timer)
(remove-hook 'erc-disconnected-hook
#'erc--server-last-reconnect-display-reset t)
(setq erc--server-reconnect-display-timer nil
erc--server-last-reconnect-count 0)))))
(defconst erc--mode-line-process-reconnecting (defconst erc--mode-line-process-reconnecting
'(:eval (erc-with-server-buffer '(:eval (erc-with-server-buffer
(and erc--server-reconnect-timer (and erc--server-reconnect-timer
@ -992,16 +823,11 @@ When `erc-server-reconnect-attempts' is a number, increment
`erc-server-reconnect-count' by INCR unconditionally." `erc-server-reconnect-count' by INCR unconditionally."
(let ((count (and (integerp erc-server-reconnect-attempts) (let ((count (and (integerp erc-server-reconnect-attempts)
(- erc-server-reconnect-attempts (- erc-server-reconnect-attempts
(cl-incf erc-server-reconnect-count (or incr 1))))) (cl-incf erc-server-reconnect-count (or incr 1))))))
(proc (buffer-local-value 'erc-server-process buffer))) (erc-display-message nil 'error (current-buffer) 'reconnecting
(erc-display-message nil 'error buffer 'reconnecting
?m erc-server-reconnect-timeout ?m erc-server-reconnect-timeout
?i (if count erc-server-reconnect-count "N") ?i (if count erc-server-reconnect-count "N")
?n (if count erc-server-reconnect-attempts "A")) ?n (if count erc-server-reconnect-attempts "A"))
(set-process-sentinel proc #'ignore)
(set-process-filter proc nil)
(delete-process proc)
(erc-update-mode-line)
(setq erc-server-reconnecting nil (setq erc-server-reconnecting nil
erc--server-reconnect-timer erc--server-reconnect-timer
(run-at-time erc-server-reconnect-timeout nil (run-at-time erc-server-reconnect-timeout nil
@ -1501,6 +1327,8 @@ Finds hooks by looking in the `erc-server-responses' hash table."
(erc-with-server-buffer (erc-with-server-buffer
(run-hook-with-args 'erc-timer-hook (erc-current-time))))) (run-hook-with-args 'erc-timer-hook (erc-current-time)))))
(add-hook 'erc-default-server-functions #'erc-handle-unknown-server-response)
(defun erc-handle-unknown-server-response (proc parsed) (defun erc-handle-unknown-server-response (proc parsed)
"Display unknown server response's message." "Display unknown server response's message."
(let ((line (concat (erc-response.sender parsed) (let ((line (concat (erc-response.sender parsed)
@ -1895,16 +1723,11 @@ add things to `%s' instead."
(unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0)) (unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0))
(erc-is-message-ctcp-and-not-action-p msg)) (erc-is-message-ctcp-and-not-action-p msg))
(if privp (if privp
(when-let ((erc-join-buffer (when erc-auto-query
(or (and (not erc-receive-query-display-defer) (let ((erc-join-buffer erc-auto-query))
erc-receive-query-display) (setq buffer (erc--open-target nick))))
(and erc-ensure-target-buffer-on-privmsg ;; A channel buffer has been killed but is still joined
(or erc-receive-query-display (setq buffer (erc--open-target tgt))))
erc-join-buffer)))))
(setq buffer (erc--open-target nick)))
;; A channel buffer has been killed but is still joined.
(when erc-ensure-target-buffer-on-privmsg
(setq buffer (erc--open-target tgt)))))
(when buffer (when buffer
(with-current-buffer buffer (with-current-buffer buffer
(when privp (erc--unhide-prompt)) (when privp (erc--unhide-prompt))
@ -1913,8 +1736,7 @@ add things to `%s' instead."
;; at this point. ;; at this point.
(erc-update-channel-member (if privp nick tgt) nick nick (erc-update-channel-member (if privp nick tgt) nick nick
privp nil nil nil nil nil host login nil nil t) privp nil nil nil nil nil host login nil nil t)
(let ((cdata (funcall erc--user-from-nick-function (let ((cdata (erc-get-channel-user nick)))
(erc-downcase nick) sndr parsed)))
(setq fnick (funcall erc-format-nick-function (setq fnick (funcall erc-format-nick-function
(car cdata) (cdr cdata)))))) (car cdata) (cdr cdata))))))
(cond (cond
@ -2054,7 +1876,7 @@ ambiguous and only useful for tokens supporting a single
primitive value." primitive value."
(if-let* ((table (or erc--isupport-params (if-let* ((table (or erc--isupport-params
(erc-with-server-buffer erc--isupport-params))) (erc-with-server-buffer erc--isupport-params)))
(value (with-memoization (gethash key table) (value (erc-compat--with-memoization (gethash key table)
(when-let ((v (assoc (symbol-name key) (when-let ((v (assoc (symbol-name key)
erc-server-parameters))) erc-server-parameters)))
(if (cdr v) (if (cdr v)
@ -2414,11 +2236,6 @@ See `erc-display-server-message'." nil
(erc-display-message parsed '(notice error) 'active (erc-display-message parsed '(notice error) 'active
's401 ?n nick/channel))) 's401 ?n nick/channel)))
(define-erc-response-handler (402)
"No such server." nil
(erc-display-message parsed '(notice error) 'active
's402 ?c (cadr (erc-response.command-args parsed))))
(define-erc-response-handler (403) (define-erc-response-handler (403)
"No such channel." nil "No such channel." nil
(erc-display-message parsed '(notice error) 'active (erc-display-message parsed '(notice error) 'active
@ -2566,7 +2383,7 @@ See `erc-display-error-notice'." nil
;; (define-erc-response-handler (323 364 365 381 382 392 393 394 395 ;; (define-erc-response-handler (323 364 365 381 382 392 393 394 395
;; 200 201 202 203 204 205 206 208 209 211 212 213 ;; 200 201 202 203 204 205 206 208 209 211 212 213
;; 214 215 216 217 218 219 241 242 243 244 249 261 ;; 214 215 216 217 218 219 241 242 243 244 249 261
;; 262 302 342 351 407 409 411 413 414 415 ;; 262 302 342 351 402 407 409 411 413 414 415
;; 423 424 436 441 443 444 467 471 472 473 KILL) ;; 423 424 436 441 443 444 467 471 472 473 KILL)
;; nil nil ;; nil nil
;; (ignore proc parsed)) ;; (ignore proc parsed))

View file

@ -52,15 +52,14 @@
;;;###autoload(autoload 'erc-button-mode "erc-button" nil t) ;;;###autoload(autoload 'erc-button-mode "erc-button" nil t)
(define-erc-module button nil (define-erc-module button nil
"This mode buttonizes all messages according to `erc-button-alist'." "This mode buttonizes all messages according to `erc-button-alist'."
((erc-button--check-nicknames-entry) ((add-hook 'erc-insert-modify-hook #'erc-button-add-buttons 'append)
(add-hook 'erc-insert-modify-hook #'erc-button-add-buttons 'append)
(add-hook 'erc-send-modify-hook #'erc-button-add-buttons 'append) (add-hook 'erc-send-modify-hook #'erc-button-add-buttons 'append)
(add-hook 'erc--tab-functions #'erc-button-next) (add-hook 'erc-complete-functions #'erc-button-next-function)
(erc--modify-local-map t "<backtab>" #'erc-button-previous)) (add-hook 'erc-mode-hook #'erc-button-setup))
((remove-hook 'erc-insert-modify-hook #'erc-button-add-buttons) ((remove-hook 'erc-insert-modify-hook #'erc-button-add-buttons)
(remove-hook 'erc-send-modify-hook #'erc-button-add-buttons) (remove-hook 'erc-send-modify-hook #'erc-button-add-buttons)
(remove-hook 'erc--tab-functions #'erc-button-next) (remove-hook 'erc-complete-functions #'erc-button-next-function)
(erc--modify-local-map nil "<backtab>" #'erc-button-previous))) (remove-hook 'erc-mode-hook #'erc-button-setup)))
;;; Variables ;;; Variables
@ -128,12 +127,13 @@ longer than `erc-fill-column'."
;; things hard to maintain. ;; things hard to maintain.
'((nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0) '((nicknames 0 erc-button-buttonize-nicks erc-nick-popup 0)
(erc-button-url-regexp 0 t browse-url-button-open-url 0) (erc-button-url-regexp 0 t browse-url-button-open-url 0)
("<URL: *\\([^<> ]+\\) *>" 0 t browse-url-button-open-url 1)
;;; ("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3) ;;; ("(\\(\\([^~\n \t@][^\n \t@]*\\)@\\([a-zA-Z0-9.:-]+\\)\\)" 1 t finger 2 3)
;; emacs internal ;; emacs internal
("[`]\\([a-zA-Z][-a-zA-Z_0-9!*<=>+]+\\)[']" ("[`]\\([a-zA-Z][-a-zA-Z_0-9!*<=>+]+\\)[']"
1 t erc-button-describe-symbol 1) 1 t erc-button-describe-symbol 1)
;; pseudo links ;; pseudo links
("\\(?:\\bInfo: ?\\|(info \\)[\"]\\(([^\"]+\\)[\"])?" 0 t info 1) ("\\bInfo:[\"]\\([^\"]+\\)[\"]" 0 t Info-goto-node 1)
("\\b\\(Ward\\|Wiki\\|WardsWiki\\|TheWiki\\):\\([A-Z][a-z]+\\([A-Z][a-z]+\\)+\\)" ("\\b\\(Ward\\|Wiki\\|WardsWiki\\|TheWiki\\):\\([A-Z][a-z]+\\([A-Z][a-z]+\\)+\\)"
0 t (lambda (page) 0 t (lambda (page)
(browse-url (concat "http://c2.com/cgi-bin/wiki?" page))) (browse-url (concat "http://c2.com/cgi-bin/wiki?" page)))
@ -165,14 +165,8 @@ REGEXP is the string matching text around the button or a symbol
BUTTON is the number of the regexp grouping actually matching the BUTTON is the number of the regexp grouping actually matching the
button. This is ignored if REGEXP is `nicknames'. button. This is ignored if REGEXP is `nicknames'.
FORM is either a boolean or a special variable whose value must FORM is a Lisp expression which must eval to true for the button to
be non-nil for the button to be added. When REGEXP is the be added.
special symbol `nicknames', FORM must be the symbol
`erc-button-buttonize-nicks'. Anything else is deprecated.
For all other entries, FORM can also be a function to call in
place of `erc-button-add-button' with the exact same arguments.
When FORM is also a special variable, ERC disregards the
variable and calls the function.
CALLBACK is the function to call when the user push this button. CALLBACK is the function to call when the user push this button.
CALLBACK can also be a symbol. Its variable value will be used CALLBACK can also be a symbol. Its variable value will be used
@ -182,7 +176,7 @@ PAR is a number of a regexp grouping whose text will be passed to
CALLBACK. There can be several PAR arguments. If REGEXP is CALLBACK. There can be several PAR arguments. If REGEXP is
`nicknames', these are ignored, and CALLBACK will be called with `nicknames', these are ignored, and CALLBACK will be called with
the nickname matched as the argument." the nickname matched as the argument."
:package-version '(ERC . "5.6") ; FIXME sync on release :package-version '(ERC . "5.5")
:type '(repeat :type '(repeat
(list :tag "Button" (list :tag "Button"
(choice :tag "Matches" (choice :tag "Matches"
@ -239,8 +233,6 @@ constituents.")
"Internal variable used to keep track of whether we've added the "Internal variable used to keep track of whether we've added the
global-level ERC button keys yet.") global-level ERC button keys yet.")
;; Maybe deprecate this function and `erc-button-keys-added' if they
;; continue to go unused for a another version (currently 5.6).
(defun erc-button-setup () (defun erc-button-setup ()
"Add ERC mode-level button movement keys. This is only done once." "Add ERC mode-level button movement keys. This is only done once."
;; Add keys. ;; Add keys.
@ -283,186 +275,35 @@ specified by `erc-button-alist'."
(concat "\\<" (regexp-quote (car elem)) "\\>") (concat "\\<" (regexp-quote (car elem)) "\\>")
entry))))))))))) entry)))))))))))
(defun erc-button--maybe-warn-arbitrary-sexp (form)
(cl-assert (not (booleanp form))) ; covered by caller
;; If a special-variable is also a function, favor the function.
(cond ((functionp form) form)
((and (symbolp form) (special-variable-p form)) (symbol-value form))
(t (unless (get 'erc-button--maybe-warn-arbitrary-sexp
'warned-arbitrary-sexp)
(put 'erc-button--maybe-warn-arbitrary-sexp
'warned-arbitrary-sexp t)
(lwarn 'erc :warning (concat "Arbitrary sexps for the third FORM"
" slot of `erc-button-alist' entries"
" have been deprecated.")))
(eval form t))))
(defun erc-button--check-nicknames-entry ()
;; This helper exists because the module is defined after its options.
(when (eq major-mode 'erc-mode)
(unless (eq (nth 1 (alist-get 'nicknames erc-button-alist))
'erc-button-buttonize-nicks)
(erc-button--display-error-notice-with-keys-and-warn
"Values other than `erc-button-buttonize-nicks' in the third slot of "
"the `nicknames' entry of `erc-button-alist' are deprecated."))))
(cl-defstruct erc-button--nick
( bounds nil :type cons
;; Indicates the nick's position in the current message. BEG is
;; normally also point.
:documentation "A cons of (BEG . END).")
( data nil :type (or null cons)
;; When non-nil, the CAR must be a non-casemapped nickname. For
;; compatibility, the CDR should probably be nil, but this may
;; have to change eventually. If non-nil, the entire cons should
;; be mutated rather than replaced because it's used as a key in
;; hash tables and text-property searches.
:documentation "A unique cons whose car is a nickname.")
( downcased nil :type (or null string)
:documentation "The case-mapped nickname sans text properties.")
( user nil :type (or null erc-server-user)
;; Not necessarily present in `erc-server-users'.
:documentation "A possibly nil or spoofed `erc-server-user'.")
( cuser nil :type (or null erc-channel-user)
;; The CDR of a value from an `erc-channel-users' table.
:documentation "A possibly nil `erc-channel-user'.")
( erc-button-face erc-button-face :type symbol
:documentation "Temp `erc-button-face' while buttonizing.")
( erc-button-nickname-face erc-button-nickname-face :type symbol
:documentation "Temp `erc-button-nickname-face' while buttonizing.")
( erc-button-mouse-face erc-button-mouse-face :type symbol
:documentation "Temp `erc-button-mouse-face' while buttonizing."))
;; This variable is intended to serve as a "core" to be wrapped by
;; (built-in) modules during setup. It's unclear whether
;; `add-function's practice of removing existing advice before
;; re-adding it is desirable when integrating modules since we're
;; mostly concerned with ensuring one "piece" precedes or follows
;; another (specific piece), which may not yet (or ever) be present.
(defvar erc-button--modify-nick-function #'identity
"Function to possibly modify aspects of nick being buttonized.
Called with one argument, an `erc-button--nick' object, or nil.
The function should return the same (or similar) object when
buttonizing ought to proceed and nil otherwise. While running,
all faces defined in `erc-button' are bound temporarily and can
be updated at will.")
(defvar-local erc-button--phantom-users nil)
(defvar erc-button--fallback-user-function #'ignore
"Function to determine `erc-server-user' if not found in the usual places.
Called with DOWNCASED-NICK, NICK, and NICK-BOUNDS when
`erc-button-add-nickname-buttons' cannot find a user object for
DOWNCASED-NICK in `erc-channel-users' or `erc-server-users'.")
(defun erc-button--add-phantom-speaker (downcased nuh _parsed)
"Stash fictitious `erc-server-user' while processing \"PRIVMSG\".
Expect DOWNCASED to be the downcased nickname, NUH to be a triple
of (NICK LOGIN HOST), and parsed to be an `erc-response' object."
(pcase-let* ((`(,nick ,login ,host) nuh)
(user (or (gethash downcased erc-button--phantom-users)
(make-erc-server-user
:nickname nick
:host (and (not (string-empty-p host)) host)
:login (and (not (string-empty-p login)) login)))))
(list (puthash downcased user erc-button--phantom-users))))
(defun erc-button--get-phantom-user (down _word _bounds)
(gethash down erc-button--phantom-users))
;; In the future, we'll most likely create temporary
;; `erc-channel-users' tables during BATCH chathistory playback, thus
;; obviating the need for this mode entirely.
(define-minor-mode erc-button--phantom-users-mode
"Minor mode to recognize unknown speakers.
Expect to be used by module setup code for creating placeholder
users on the fly during history playback. Treat an unknown
\"PRIVMSG\" speaker, like \"<bob>\", as if they previously
appeared in a prior \"353\" message and are thus a known member
of the channel. However, don't bother creating an actual
`erc-channel-user' object because their status prefix is unknown.
Instead, just spoof an `erc-server-user' and stash it during
\"PRIVMSG\" handling via `erc--user-from-nick-function' and
retrieve it during buttonizing via
`erc-button--fallback-user-function'."
:interactive nil
(if erc-button--phantom-users-mode
(progn
(add-function :after-until (local 'erc--user-from-nick-function)
#'erc-button--add-phantom-speaker '((depth . -50)))
(add-function :after-until (local 'erc-button--fallback-user-function)
#'erc-button--get-phantom-user '((depth . 50)))
(setq erc-button--phantom-users (make-hash-table :test #'equal)))
(remove-function (local 'erc--user-from-nick-function)
#'erc-button--add-phantom-speaker)
(remove-function (local 'erc-button--fallback-user-function)
#'erc-button--get-phantom-user)
(kill-local-variable 'erc-nicks--phantom-users)))
(defun erc-button-add-nickname-buttons (entry) (defun erc-button-add-nickname-buttons (entry)
"Search through the buffer for nicknames, and add buttons." "Search through the buffer for nicknames, and add buttons."
(let ((form (nth 2 entry)) (let ((form (nth 2 entry))
(fun (nth 3 entry)) (fun (nth 3 entry))
bounds word) bounds word)
(when (eq form 'erc-button-buttonize-nicks) (when (or (eq t form)
(setq form (and (symbol-value form) erc-button--modify-nick-function))) (eval form t))
(when (or (functionp form)
(eq t form)
(and form (erc-button--maybe-warn-arbitrary-sexp form)))
(goto-char (point-min)) (goto-char (point-min))
(while (erc-forward-word) (while (erc-forward-word)
(when (setq bounds (erc-bounds-of-word-at-point)) (when (setq bounds (erc-bounds-of-word-at-point))
(setq word (buffer-substring-no-properties (setq word (buffer-substring-no-properties
(car bounds) (cdr bounds))) (car bounds) (cdr bounds)))
(let* ((erc-button-face erc-button-face) (when (or (and (erc-server-buffer-p) (erc-get-server-user word))
(erc-button-mouse-face erc-button-mouse-face) (and erc-channel-users (erc-get-channel-user word)))
(erc-button-nickname-face erc-button-nickname-face)
(down (erc-downcase word))
(cuser (and erc-channel-users
(gethash down erc-channel-users)))
(user (or (and cuser (car cuser))
(and erc-server-users
(gethash down erc-server-users))
(funcall erc-button--fallback-user-function
down word bounds)))
(data (list word)))
(when (or (not (functionp form))
(and-let* ((user)
(obj (funcall form (make-erc-button--nick
:bounds bounds :data data
:downcased down :user user
:cuser (cdr cuser)))))
(setq bounds (erc-button--nick-bounds obj)
data (erc-button--nick-data obj)
erc-button-mouse-face
(erc-button--nick-erc-button-mouse-face obj)
erc-button-nickname-face
(erc-button--nick-erc-button-nickname-face obj)
erc-button-face
(erc-button--nick-erc-button-face obj))))
(erc-button-add-button (car bounds) (cdr bounds) (erc-button-add-button (car bounds) (cdr bounds)
fun t data)))))))) fun t (list word))))))))
(defun erc-button-add-buttons-1 (regexp entry) (defun erc-button-add-buttons-1 (regexp entry)
"Search through the buffer for matches to ENTRY and add buttons." "Search through the buffer for matches to ENTRY and add buttons."
(goto-char (point-min)) (goto-char (point-min))
(let (buttonizer) (while (re-search-forward regexp nil t)
(while
(and (re-search-forward regexp nil t)
(or buttonizer
(setq buttonizer
(and-let*
((raw-form (nth 2 entry))
(res (or (eq t raw-form)
(erc-button--maybe-warn-arbitrary-sexp
raw-form))))
(if (functionp res) res #'erc-button-add-button)))))
(let ((start (match-beginning (nth 1 entry))) (let ((start (match-beginning (nth 1 entry)))
(end (match-end (nth 1 entry))) (end (match-end (nth 1 entry)))
(form (nth 2 entry))
(fun (nth 3 entry)) (fun (nth 3 entry))
(data (mapcar #'match-string-no-properties (nthcdr 4 entry)))) (data (mapcar #'match-string-no-properties (nthcdr 4 entry))))
(funcall buttonizer start end fun nil data regexp))))) (when (or (eq t form)
(eval form t))
(erc-button-add-button start end fun nil data regexp)))))
(defun erc-button-remove-old-buttons () (defun erc-button-remove-old-buttons ()
"Remove all existing buttons. "Remove all existing buttons.
@ -564,7 +405,6 @@ call it with the value of the `erc-data' text property."
(defun erc-button-next-function () (defun erc-button-next-function ()
"Pseudo completion function that actually jumps to the next button. "Pseudo completion function that actually jumps to the next button.
For use on `completion-at-point-functions'." For use on `completion-at-point-functions'."
(declare (obsolete erc-nickserv-identify "30.1"))
;; FIXME: This is an abuse of completion-at-point-functions. ;; FIXME: This is an abuse of completion-at-point-functions.
(when (< (point) (erc-beg-of-input-line)) (when (< (point) (erc-beg-of-input-line))
(let ((start (point))) (let ((start (point)))
@ -582,73 +422,27 @@ For use on `completion-at-point-functions'."
(error "No next button")) (error "No next button"))
t))))) t)))))
(defvar erc-button--prev-next-predicate-functions (defun erc-button-next ()
'(erc-button--end-of-button-p) "Go to the next button in this buffer."
"Abnormal hook whose members can return non-nil to continue searching. (interactive)
Otherwise, if all members return nil, point will stay at the (let ((f (erc-button-next-function)))
current button. Called with a single arg, a buffer position (if f (funcall f))))
greater than `point-min' with a text property of `erc-callback'.")
(defun erc-button--end-of-button-p (point) (defun erc-button-previous ()
(get-text-property (1- point) 'erc-callback)) "Go to the previous button in this buffer."
(interactive)
(defun erc--button-next (arg) (let ((here (point)))
(let* ((nextp (prog1 (>= arg 1) (setq arg (max 1 (abs arg))))) (when (< here (erc-beg-of-input-line))
(search-fn (if nextp (while (and (get-text-property here 'erc-callback)
#'next-single-char-property-change (not (= here (point-min))))
#'previous-single-char-property-change)) (setq here (1- here)))
(start (point)) (while (and (not (get-text-property here 'erc-callback))
(p start)) (not (= here (point-min))))
(while (progn (setq here (1- here)))
;; Break out of current search context. (if (> here (point-min))
(when-let ((low (max (point-min) (1- (pos-bol)))) (goto-char here)
(high (min (point-max) (1+ (pos-eol)))) (error "No previous button"))
(prop (get-text-property p 'erc-callback)) t)))
(q (if nextp
(text-property-not-all p high
'erc-callback prop)
(funcall search-fn p 'erc-callback nil low)))
((< low q high)))
(setq p q))
;; Assume that buttons occur frequently enough that
;; omitting LIMIT is acceptable.
(while
(and (setq p (funcall search-fn p 'erc-callback))
(if nextp (< p erc-insert-marker) (/= p (point-min)))
(run-hook-with-args-until-success
'erc-button--prev-next-predicate-functions p)))
(and arg
(< (point-min) p erc-insert-marker)
(goto-char p)
(not (zerop (cl-decf arg))))))
(when (= (point) start)
(user-error (if nextp "No next button" "No previous button")))
t))
(defun erc-button-next (&optional arg)
"Go to the ARGth next button."
(declare (advertised-calling-convention (arg) "30.1"))
(interactive "p")
(setq arg (pcase arg ((pred listp) (prefix-numeric-value arg)) (_ arg)))
(erc--button-next arg))
(defun erc-button-previous (&optional arg)
"Go to ARGth previous button."
(declare (advertised-calling-convention (arg) "30.1"))
(interactive "p")
(setq arg (pcase arg ((pred listp) (prefix-numeric-value arg)) (_ arg)))
(erc--button-next (- arg)))
(defun erc-button-previous-of-nick (arg)
"Go to ARGth previous button for nick at point."
(interactive "p")
(if-let* ((prop (get-text-property (point) 'erc-data))
(erc-button--prev-next-predicate-functions
(cons (lambda (p)
(not (equal (get-text-property p 'erc-data) prop)))
erc-button--prev-next-predicate-functions)))
(erc--button-next (- arg))
(user-error "No nick at point")))
(defun erc-browse-emacswiki (thing) (defun erc-browse-emacswiki (thing)
"Browse to THING in the emacs-wiki." "Browse to THING in the emacs-wiki."
@ -717,70 +511,6 @@ and `apropos' for other symbols."
(message "@%s is %d:%02d local time" (message "@%s is %d:%02d local time"
beats hours minutes))) beats hours minutes)))
(defun erc-button--display-error-with-buttons
(from to fun nick-p &optional data regexp)
"Replace command in region with keys and return new bounds"
(let* ((o (buffer-substring from to))
(s (substitute-command-keys o))
(erc-button-face (and (equal o s) erc-button-face)))
(delete-region from to)
(insert s)
(erc-button-add-button from (point) fun nick-p data regexp)))
;;;###autoload
(defun erc-button--display-error-notice-with-keys (&optional parsed buffer
&rest strings)
"Add help keys to STRINGS for configuration-related admonishments.
Return inserted result. Expect PARSED to be an `erc-response'
object, a string, or nil. Expect BUFFER to be a buffer, a string,
or nil. As a special case, allow PARSED to be a buffer as long
as BUFFER is a string or nil. If STRINGS contains any trailing
non-strings, concatenate leading string members before applying
`format'. Otherwise, just concatenate everything."
(when (stringp buffer)
(push buffer strings)
(setq buffer nil))
(when (stringp parsed)
(push parsed strings)
(setq parsed nil))
(when (bufferp parsed)
(cl-assert (null buffer))
(setq buffer parsed
parsed nil))
(let* ((op (if (seq-every-p #'stringp (cdr strings))
#'concat
(let ((head (pop strings)))
(while (stringp (car strings))
(setq head (concat head (pop strings))))
(push head strings))
#'format))
(string (apply op strings))
(erc-insert-post-hook
(cons (lambda ()
(setq string (buffer-substring (point-min)
(1- (point-max)))))
erc-insert-post-hook))
(erc-button-alist
`((,(rx "\\[" (group (+ (not "]"))) "]") 0
erc-button--display-error-with-buttons
erc-button-describe-symbol 1)
,@erc-button-alist)))
(erc-display-message parsed '(notice error) (or buffer 'active) string)
string))
;;;###autoload
(defun erc-button--display-error-notice-with-keys-and-warn (&rest args)
"Like `erc-button--display-error-notice-with-keys' but also warn."
(let ((string (apply #'erc-button--display-error-notice-with-keys args)))
(with-temp-buffer
(insert string)
(goto-char (point-min))
(with-syntax-table lisp-mode-syntax-table
(skip-syntax-forward "^-"))
(forward-char)
(display-warning
'erc (buffer-substring-no-properties (point) (point-max))))))
(provide 'erc-button) (provide 'erc-button)
;;; erc-button.el ends here ;;; erc-button.el ends here

View file

@ -89,7 +89,6 @@ character not found in IRC nicknames to avoid confusion."
;;; Define module: ;;; Define module:
;;;###autoload(autoload 'erc-capab-identify-mode "erc-capab" nil t) ;;;###autoload(autoload 'erc-capab-identify-mode "erc-capab" nil t)
(put 'capab-identify 'erc-group 'erc-capab)
(define-erc-module capab-identify nil (define-erc-module capab-identify nil
"Handle dancer-ircd's CAPAB IDENTIFY-MSG and IDENTIFY-CTCP." "Handle dancer-ircd's CAPAB IDENTIFY-MSG and IDENTIFY-CTCP."
;; append so that `erc-server-parameters' is already set by `erc-server-005' ;; append so that `erc-server-parameters' is already set by `erc-server-005'

View file

@ -30,35 +30,19 @@
(defvar erc--casemapping-rfc1459-strict) (defvar erc--casemapping-rfc1459-strict)
(defvar erc-channel-users) (defvar erc-channel-users)
(defvar erc-dbuf) (defvar erc-dbuf)
(defvar erc-insert-this)
(defvar erc-log-p) (defvar erc-log-p)
(defvar erc-modules)
(defvar erc-send-this)
(defvar erc-server-process)
(defvar erc-server-users) (defvar erc-server-users)
(defvar erc-session-server) (defvar erc-session-server)
(declare-function erc--get-isupport-entry "erc-backend" (key &optional single)) (declare-function erc--get-isupport-entry "erc-backend" (key &optional single))
(declare-function erc-get-buffer "erc" (target &optional proc)) (declare-function erc-get-buffer "erc" (target &optional proc))
(declare-function erc-server-buffer "erc" nil) (declare-function erc-server-buffer "erc" nil)
(declare-function widget-apply-action "wid-edit" (widget &optional event))
(declare-function widget-at "wid-edit" (&optional pos))
(declare-function widget-create-child-and-convert "wid-edit"
(parent type &rest args))
(declare-function widget-default-format-handler "wid-edit" (widget escape))
(declare-function widget-get-sibling "wid-edit" (widget))
(declare-function widget-move "wid-edit" (arg &optional suppress-echo))
(declare-function widget-type "wid-edit" (widget))
(cl-defstruct erc-input (cl-defstruct erc-input
string insertp sendp refoldp) string insertp sendp)
(cl-defstruct (erc--input-split (:include erc-input (cl-defstruct (erc--input-split (:include erc-input))
(string :read-only) lines cmdp)
(insertp erc-insert-this)
(sendp erc-send-this)))
(lines nil :type (list-of string))
(cmdp nil :type boolean))
(cl-defstruct (erc-server-user (:type vector) :named) (cl-defstruct (erc-server-user (:type vector) :named)
;; User data ;; User data
@ -101,52 +85,45 @@
(contents "" :type string) (contents "" :type string)
(tags '() :type list)) (tags '() :type list))
;; After dropping 28, we can use prefixed "erc-autoload" cookies. ;; TODO move goodies modules here after 29 is released.
(defconst erc--features-to-modules
'((erc-pcomplete completion pcomplete)
(erc-capab capab-identify)
(erc-join autojoin)
(erc-page page ctcp-page)
(erc-sound sound ctcp-sound)
(erc-stamp stamp timestamp)
(erc-services services nickserv))
"Migration alist mapping a library feature to module names.
Keys need not be unique: a library may define more than one
module. Sometimes a module's downcased alias will be its
canonical name.")
(defconst erc--modules-to-features
(let (pairs)
(pcase-dolist (`(,feature . ,names) erc--features-to-modules)
(dolist (name names)
(push (cons name feature) pairs)))
(nreverse pairs))
"Migration alist mapping a module's name to its home library feature.")
(defconst erc--module-name-migrations
(let (pairs)
(pcase-dolist (`(,_ ,canonical . ,rest) erc--features-to-modules)
(dolist (obsolete rest)
(push (cons obsolete canonical) pairs)))
pairs)
"Association list of obsolete module names to canonical names.")
(defun erc--normalize-module-symbol (symbol) (defun erc--normalize-module-symbol (symbol)
"Return preferred SYMBOL for `erc--modules'." "Return preferred SYMBOL for `erc-modules'."
(while-let ((canonical (get symbol 'erc--module)) (setq symbol (intern (downcase (symbol-name symbol))))
((not (eq canonical symbol)))) (or (cdr (assq symbol erc--module-name-migrations)) symbol))
(setq symbol canonical))
symbol)
(defvar erc--inside-mode-toggle-p nil
"Non-nil when a module's mode toggle is updating module membership.
This serves as a flag to inhibit the mutual recursion that would
otherwise occur between an ERC-defined minor-mode function, such
as `erc-services-mode', and the custom-set function for
`erc-modules'. For historical reasons, the latter calls
`erc-update-modules', which, in turn, enables the minor-mode
functions for all member modules. Also non-nil when a mode's
widget runs its set function.")
(defun erc--favor-changed-reverted-modules-state (name op)
"Be more nuanced in displaying Custom state of `erc-modules'.
When `customized-value' differs from `saved-value', allow widget
to behave normally and show \"SET for current session\", as
though `customize-set-variable' or similar had been applied.
However, when `customized-value' and `standard-value' match but
differ from `saved-value', prefer showing \"CHANGED outside
Customize\" to prevent the widget from seeing a `standard'
instead of a `set' state, which precludes any actual saving."
;; Although the button "Apply and save" is fortunately grayed out,
;; `Custom-save' doesn't actually save (users must click the magic
;; state button instead). The default behavior described in the doc
;; string is intentional and was introduced by bug#12864 "Make state
;; button interaction less confusing". However, it is unfriendly to
;; rogue libraries (like ours) that insist on mutating user options
;; as a matter of course.
(custom-load-symbol 'erc-modules)
(funcall (get 'erc-modules 'custom-set) 'erc-modules
(funcall op (erc--normalize-module-symbol name) erc-modules))
(when (equal (pcase (get 'erc-modules 'saved-value)
(`((quote ,saved) saved)))
erc-modules)
(customize-mark-as-set 'erc-modules)))
(defun erc--assemble-toggle (localp name ablsym mode val body) (defun erc--assemble-toggle (localp name ablsym mode val body)
(let ((arg (make-symbol "arg"))) (let ((arg (make-symbol "arg")))
`(defun ,ablsym ,(if localp `(&optional ,arg) '()) `(defun ,ablsym ,(if localp `(&optional ,arg) '())
,(erc--fill-module-docstring ,(concat
(if val "Enable" "Disable") (if val "Enable" "Disable")
" ERC " (symbol-name name) " mode." " ERC " (symbol-name name) " mode."
(when localp (when localp
@ -160,133 +137,14 @@ instead of a `set' state, which precludes any actual saving."
(,ablsym)) (,ablsym))
(setq ,mode ,val) (setq ,mode ,val)
,@body))) ,@body)))
;; No need for `default-value', etc. because a buffer-local `(,(if val
;; `erc-modules' only influences the next session and `(cl-pushnew ',(erc--normalize-module-symbol name)
;; doesn't survive the major-mode reset that soon follows. erc-modules)
`((unless `(setq erc-modules (delq ',(erc--normalize-module-symbol name)
(or erc--inside-mode-toggle-p
,@(let ((v `(memq ',(erc--normalize-module-symbol name)
erc-modules))) erc-modules)))
`(,(if val v `(not ,v)))))
(let ((erc--inside-mode-toggle-p t))
(erc--favor-changed-reverted-modules-state
',name #',(if val 'cons 'delq))))
(setq ,mode ,val) (setq ,mode ,val)
,@body))))) ,@body)))))
;; This is a migration helper that determines a module's `:group'
;; keyword argument from its name or alias. A (global) module's minor
;; mode variable appears under the group's Custom menu. Like
;; `erc--normalize-module-symbol', it must run when the module's
;; definition (rather than that of `define-erc-module') is expanded.
;; For corner cases in which this fails or the catch-all of `erc' is
;; more inappropriate, (global) modules can declare a top-level
;;
;; (put 'foo 'erc-group 'erc-bar)
;;
;; where `erc-bar' is the group and `foo' is the normalized module.
;; Do this *before* the module's definition. If `define-erc-module'
;; ever accepts arbitrary keywords, passing an explicit `:group' will
;; obviously be preferable.
(defun erc--find-group (&rest symbols)
(catch 'found
(dolist (s symbols)
(let* ((downed (downcase (symbol-name s)))
(known (intern-soft (concat "erc-" downed))))
(when (and known
(or (get known 'group-documentation)
(rassq known custom-current-group-alist)))
(throw 'found known))
(when (setq known (intern-soft (concat "erc-" downed "-mode")))
(when-let ((found (custom-group-of-mode known)))
(throw 'found found))))
(when-let ((found (get (erc--normalize-module-symbol s) 'erc-group)))
(throw 'found found)))
'erc))
;; This exists as a separate, top-level function to prevent the byte
;; compiler from warning about widget-related dependencies not being
;; loaded at runtime.
(defun erc--tick-module-checkbox (name &rest _) ; `name' must be normalized
(customize-variable-other-window 'erc-modules)
;; Move to `erc-modules' section.
(while (not (eq (widget-type (widget-at)) 'checkbox))
(widget-move 1 t))
;; This search for a checkbox can fail when `name' refers to a
;; third-party module that modifies `erc-modules' (improperly) on
;; load.
(let (w)
(while (and (eq (widget-type (widget-at)) 'checkbox)
(not (and (setq w (widget-get-sibling (widget-at)))
(eq (widget-value w) name))))
(setq w nil)
(widget-move 1 t)) ; the `suppress-echo' arg exists in 27.2
(unless w
(error "Failed to find %s in `erc-modules' checklist" name))
(widget-apply-action (widget-at))
(message "Hit %s to apply or %s to apply and save."
(substitute-command-keys "\\[Custom-set]")
(substitute-command-keys "\\[Custom-save]"))))
;; This stands apart to avoid needing forward declarations for
;; `wid-edit' functions in every file requiring `erc-common'.
(defun erc--make-show-me-widget (widget escape &rest plist)
(if (eq escape ?i)
(apply #'widget-create-child-and-convert widget 'push-button plist)
(widget-default-format-handler widget escape)))
(defun erc--prepare-custom-module-type (name)
`(let* ((name (erc--normalize-module-symbol ',name))
(fmtd (format " `%s' " name)))
`(boolean
:format "%{%t%}: %i %[Deprecated Toggle%] %v \n%h\n"
:format-handler
,(lambda (widget escape)
(erc--make-show-me-widget
widget escape
:button-face '(custom-variable-obsolete custom-button)
:tag "Show Me"
:action (apply-partially #'erc--tick-module-checkbox name)
:help-echo (lambda (_)
(let ((hasp (memq name erc-modules)))
(concat (if hasp "Remove" "Add") fmtd
(if hasp "from" "to")
" `erc-modules'.")))))
:action widget-toggle-action
:documentation-property
,(lambda (_)
(let ((hasp (memq name erc-modules)))
(concat
"Setting a module's minor-mode variable is "
(propertize "ineffective" 'face 'error)
".\nPlease " (if hasp "remove" "add") fmtd
(if hasp "from" "to") " `erc-modules' directly instead.\n"
"You can do so now by clicking "
(propertize "Show Me" 'face 'custom-variable-obsolete)
" above."))))))
(defun erc--fill-module-docstring (&rest strings)
(with-temp-buffer
(emacs-lisp-mode)
(insert "(defun foo ()\n"
(format "%S" (apply #'concat strings))
"\n(ignore))")
(goto-char (point-min))
(forward-line 2)
(let ((emacs-lisp-docstring-fill-column 65)
(sentence-end-double-space t))
(fill-paragraph))
(goto-char (point-min))
(nth 3 (read (current-buffer)))))
(defmacro erc--find-feature (name alias)
`(pcase (erc--find-group ',name ,(and alias (list 'quote alias)))
('erc (and-let* ((file (or (macroexp-file-name) buffer-file-name)))
(intern (file-name-base file))))
(v v)))
(defmacro define-erc-module (name alias doc enable-body disable-body (defmacro define-erc-module (name alias doc enable-body disable-body
&optional local-p) &optional local-p)
"Define a new minor mode using ERC conventions. "Define a new minor mode using ERC conventions.
@ -321,20 +179,21 @@ Example:
(declare (doc-string 3) (indent defun)) (declare (doc-string 3) (indent defun))
(let* ((sn (symbol-name name)) (let* ((sn (symbol-name name))
(mode (intern (format "erc-%s-mode" (downcase sn)))) (mode (intern (format "erc-%s-mode" (downcase sn))))
(group (intern (format "erc-%s" (downcase sn))))
(enable (intern (format "erc-%s-enable" (downcase sn)))) (enable (intern (format "erc-%s-enable" (downcase sn))))
(disable (intern (format "erc-%s-disable" (downcase sn))))) (disable (intern (format "erc-%s-disable" (downcase sn)))))
`(progn `(progn
(define-minor-mode (define-minor-mode
,mode ,mode
,(erc--fill-module-docstring (format "Toggle ERC %s mode. ,(format "Toggle ERC %S mode.
With a prefix argument ARG, enable %s if ARG is positive, With a prefix argument ARG, enable %s if ARG is positive,
and disable it otherwise. If called from Lisp, enable the mode and disable it otherwise. If called from Lisp, enable the mode
if ARG is omitted or nil. if ARG is omitted or nil.
\n%s" name name doc)) %s" name name doc)
:global ,(not local-p) ;; FIXME: We don't know if this group exists, so this `:group' may
:group (erc--find-group ',name ,(and alias (list 'quote alias))) ;; actually just silence a valid warning about the fact that the var
,@(unless local-p `(:require ',(erc--find-feature name alias))) ;; is not associated with any group.
,@(unless local-p `(:type ,(erc--prepare-custom-module-type name))) :global ,(not local-p) :group (quote ,group)
(if ,mode (if ,mode
(,enable) (,enable)
(,disable))) (,disable)))
@ -390,16 +249,10 @@ See also `with-current-buffer'.
"Execute BODY in the current ERC server buffer. "Execute BODY in the current ERC server buffer.
If no server buffer exists, return nil." If no server buffer exists, return nil."
(declare (indent 0) (debug (body))) (declare (indent 0) (debug (body)))
(let ((varp (and (symbolp (car body)) (let ((buffer (make-symbol "buffer")))
(not (cdr body)) `(let ((,buffer (erc-server-buffer)))
(special-variable-p (car body)))) (when (buffer-live-p ,buffer)
(buffer (make-symbol "buffer"))) (with-current-buffer ,buffer
`(when-let* (((processp erc-server-process))
(,buffer (process-buffer erc-server-process))
((buffer-live-p ,buffer)))
,(if varp
`(buffer-local-value ',(car body) ,buffer)
`(with-current-buffer ,buffer
,@body))))) ,@body)))))
(defmacro erc-with-all-buffers-of-server (process pred &rest forms) (defmacro erc-with-all-buffers-of-server (process pred &rest forms)

View file

@ -32,50 +32,7 @@
;;; Code: ;;; Code:
(require 'compat nil 'noerror) (require 'compat nil 'noerror)
(eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'cl-lib) (require 'url-parse))
;; Except for the "erc-" namespacing, these two definitions should be
;; continuously updated to match the latest upstream ones verbatim.
;; Although they're pretty simple, it's likely not worth checking for
;; and possibly deferring to the non-prefixed versions.
;;
;; BEGIN Compat macros
;;;; Macros for extended compatibility function calls
(defmacro erc-compat-function (fun)
"Return compatibility function symbol for FUN.
If the Emacs version provides a sufficiently recent version of
FUN, the symbol FUN is returned itself. Otherwise the macro
returns the symbol of a compatibility function which supports the
behavior and calling convention of the current stable Emacs
version. For example Compat 29.1 will provide compatibility
functions which implement the behavior and calling convention of
Emacs 29.1.
See also `compat-call' to directly call compatibility functions."
(let ((compat (intern (format "compat--%s" fun))))
`#',(if (fboundp compat) compat fun)))
(defmacro erc-compat-call (fun &rest args)
"Call compatibility function or macro FUN with ARGS.
A good example function is `plist-get' which was extended with an
additional predicate argument in Emacs 29.1. The compatibility
function, which supports this additional argument, can be
obtained via (compat-function plist-get) and called
via (compat-call plist-get plist prop predicate). It is not
possible to directly call (plist-get plist prop predicate) on
Emacs older than 29.1, since the original `plist-get' function
does not yet support the predicate argument. Note that the
Compat library never overrides existing functions.
See also `compat-function' to lookup compatibility functions."
(let ((compat (intern (format "compat--%s" fun))))
`(,(if (fboundp compat) compat fun) ,@args)))
;; END Compat macros
;;;###autoload(autoload 'erc-define-minor-mode "erc-compat") ;;;###autoload(autoload 'erc-define-minor-mode "erc-compat")
(define-obsolete-function-alias 'erc-define-minor-mode (define-obsolete-function-alias 'erc-define-minor-mode
@ -411,8 +368,16 @@ If START or END is negative, it counts from the end."
;;;; Misc 29.1 ;;;; Misc 29.1
(defmacro erc-compat--with-memoization (table &rest forms)
(declare (indent defun))
(cond
((fboundp 'with-memoization)
`(with-memoization ,table ,@forms)) ; 29.1
((fboundp 'cl--generic-with-memoization)
`(cl--generic-with-memoization ,table ,@forms))
(t `(progn ,@forms))))
(defvar url-irc-function) (defvar url-irc-function)
(declare-function url-type "url-parse" (cl-x))
(defun erc-compat--29-browse-url-irc (string &rest _) (defun erc-compat--29-browse-url-irc (string &rest _)
(require 'url-irc) (require 'url-irc)
@ -444,28 +409,6 @@ If START or END is negative, it counts from the end."
(cons '("\\`irc6?s?://" . erc-compat--29-browse-url-irc) (cons '("\\`irc6?s?://" . erc-compat--29-browse-url-irc)
existing)))))) existing))))))
;;;; Misc 28.1
(defvar comint-file-name-quote-list)
(defvar shell-file-name-quote-list)
(declare-function shell--parse-pcomplete-arguments "shell" nil)
(defun erc-compat--28-split-string-shell-command (string)
(require 'comint)
(require 'shell)
(with-temp-buffer
(insert string)
(let ((comint-file-name-quote-list shell-file-name-quote-list))
(car (shell--parse-pcomplete-arguments)))))
(defmacro erc-compat--split-string-shell-command (string)
;; Autoloaded in Emacs 28.
(list (if (fboundp 'split-string-shell-command)
'split-string-shell-command
'erc-compat--28-split-string-shell-command)
string))
(provide 'erc-compat) (provide 'erc-compat)
;;; erc-compat.el ends here ;;; erc-compat.el ends here

View file

@ -43,7 +43,7 @@
;; /dcc chat nick - Either accept pending chat offer from nick, or offer ;; /dcc chat nick - Either accept pending chat offer from nick, or offer
;; DCC chat to nick ;; DCC chat to nick
;; /dcc close type [nick] - Close DCC connection (SEND/GET/CHAT) with nick ;; /dcc close type [nick] - Close DCC connection (SEND/GET/CHAT) with nick
;; /dcc get [-t][-s] nick [--] file - Accept DCC offer from nick ;; /dcc get [-t][-s] nick [file] - Accept DCC offer from nick
;; /dcc list - List all DCC offers/connections ;; /dcc list - List all DCC offers/connections
;; /dcc send nick file - Offer DCC SEND to nick ;; /dcc send nick file - Offer DCC SEND to nick
@ -389,18 +389,12 @@ If this is nil, then the current value of `default-directory' is used."
:type '(choice (const :value nil :tag "Default directory") directory)) :type '(choice (const :value nil :tag "Default directory") directory))
;;;###autoload ;;;###autoload
(defun erc-cmd-DCC (line &rest compat-args) (defun erc-cmd-DCC (cmd &rest args)
"Parser for /dcc command. "Parser for /dcc command.
This figures out the dcc subcommand and calls the appropriate routine to This figures out the dcc subcommand and calls the appropriate routine to
handle it. The function dispatched should be named \"erc-dcc-do-FOO-command\", handle it. The function dispatched should be named \"erc-dcc-do-FOO-command\",
where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc." where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc."
(let (cmd args) (when cmd
;; Called as library function (i.e., not directly as /dcc)
(if compat-args
(setq cmd line
args compat-args)
(setq args (delete "" (erc-compat--split-string-shell-command line))
cmd (pop args)))
(let ((fn (intern-soft (concat "erc-dcc-do-" (upcase cmd) "-command")))) (let ((fn (intern-soft (concat "erc-dcc-do-" (upcase cmd) "-command"))))
(if fn (if fn
(apply fn erc-server-process args) (apply fn erc-server-process args)
@ -410,16 +404,8 @@ where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc."
(apropos "erc-dcc-do-.*-command") (apropos "erc-dcc-do-.*-command")
t)))) t))))
(put 'erc-cmd-DCC 'do-not-parse-args t)
(autoload 'pcomplete-erc-all-nicks "erc-pcomplete") (autoload 'pcomplete-erc-all-nicks "erc-pcomplete")
;;;###autoload(put 'erc-cmd-DCC 'erc--cmd-help 'erc-dcc--cmd-help)
(defun erc-dcc--cmd-help (&rest args)
(describe-function
(or (and args (intern-soft (concat "erc-dcc-do-"
(upcase (car args)) "-command")))
'erc-cmd-DCC)))
;;;###autoload ;;;###autoload
(defun pcomplete/erc-mode/DCC () (defun pcomplete/erc-mode/DCC ()
"Provide completion for the /DCC command." "Provide completion for the /DCC command."
@ -444,20 +430,15 @@ where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc."
(eq (plist-get elt :type) 'GET)) (eq (plist-get elt :type) 'GET))
erc-dcc-list))) erc-dcc-list)))
('send (pcomplete-erc-all-nicks)))) ('send (pcomplete-erc-all-nicks))))
(when (equal "get" (downcase (pcomplete-arg 'first 1)))
(pcomplete-opt "-"))
(pcomplete-here (pcomplete-here
(pcase (intern (downcase (pcomplete-arg 'first 1))) (pcase (intern (downcase (pcomplete-arg 'first 1)))
('get (mapcar (lambda (elt) ('get (mapcar (lambda (elt) (plist-get elt :file))
(combine-and-quote-strings (list (plist-get elt :file))))
(cl-remove-if-not (cl-remove-if-not
(lambda (elt) (lambda (elt)
(and (eq (plist-get elt :type) 'GET) (and (eq (plist-get elt :type) 'GET)
(erc-nick-equal-p (erc-extract-nick (erc-nick-equal-p (erc-extract-nick
(plist-get elt :nick)) (plist-get elt :nick))
(pcase (pcomplete-arg 1) (pcomplete-arg 1))))
("--" (pcomplete-arg 2))
(v v)))))
erc-dcc-list))) erc-dcc-list)))
('close (mapcar #'erc-dcc-nick ('close (mapcar #'erc-dcc-nick
(cl-remove-if-not (cl-remove-if-not
@ -523,33 +504,16 @@ At least one of TYPE and NICK must be provided."
?n (erc-extract-nick (plist-get ret :nick)))))) ?n (erc-extract-nick (plist-get ret :nick))))))
t)) t))
(defun erc-dcc-do-GET-command (proc &rest args) (defun erc-dcc-do-GET-command (proc nick &rest file)
"Perform a DCC GET command. "Do a DCC GET command. NICK is the person who is sending the file.
Recognize input conforming to the following usage syntax: FILE is the filename. If FILE is split into multiple arguments,
re-join the arguments, separated by a space.
/DCC GET [-t|-s] nick [--] filename PROC is the server process."
(let* ((args (seq-group-by (lambda (s) (eq ?- (aref s 0))) (cons nick file)))
nick The person who is sending the file.
filename The filename to be downloaded. Can be split into multiple
arguments that are then joined by a space.
flags \"-t\" sets `:turbo' in `erc-dcc-list'
\"-s\" sets `:secure' in `erc-dcc-list'
\"--\" indicates end of options
All of which are optional.
Expect PROC to be the server process and ARGS to contain
everything after the subcommand \"GET\" in the usage description
above."
;; Despite the advertised syntax above, we currently respect flags
;; in these positions: [flag] nick [flag] filename [flag]
(let* ((trailing (and-let* ((trailing (member "--" args)))
(setq args (butlast args (length trailing)))
(cdr trailing)))
(args (seq-group-by (lambda (s) (eq ?- (aref s 0))) args))
(flags (prog1 (cdr (assq t args)) (flags (prog1 (cdr (assq t args))
(setq args (nconc (cdr (assq nil args)) trailing)))) (setq args (cdr (assq nil args))
(nick (pop args)) nick (pop args)
(file (and args (mapconcat #'identity args " "))) file (and args (mapconcat #'identity args " ")))))
(elt (erc-dcc-member :nick nick :type 'GET :file file)) (elt (erc-dcc-member :nick nick :type 'GET :file file))
(filename (or file (plist-get elt :file) "unknown"))) (filename (or file (plist-get elt :file) "unknown")))
(if elt (if elt

View file

@ -28,9 +28,6 @@
;; `erc-fill-mode' to switch it on. Customize `erc-fill-function' to ;; `erc-fill-mode' to switch it on. Customize `erc-fill-function' to
;; change the style. ;; change the style.
;; TODO: redo `erc-fill-wrap-nudge' using transient after ERC drops
;; support for Emacs 27.
;;; Code: ;;; Code:
(require 'erc) (require 'erc)
@ -41,18 +38,30 @@
:group 'erc) :group 'erc)
;;;###autoload(autoload 'erc-fill-mode "erc-fill" nil t) ;;;###autoload(autoload 'erc-fill-mode "erc-fill" nil t)
(define-erc-module fill nil (define-minor-mode erc-fill-mode
"Manage filling in ERC buffers. "Toggle ERC fill mode.
With a prefix argument ARG, enable ERC fill mode if ARG is
positive, and disable it otherwise. If called from Lisp, enable
the mode if ARG is omitted or nil.
ERC fill mode is a global minor mode. When enabled, messages in ERC fill mode is a global minor mode. When enabled, messages in
the channel buffers are filled." the channel buffers are filled."
;; FIXME ensure a consistent ordering relative to hook members from :global t
;; other modules. Ideally, this module's processing should happen (if erc-fill-mode
;; after "morphological" modifications to a message's text but (erc-fill-enable)
;; before superficial decorations. (erc-fill-disable)))
((add-hook 'erc-insert-modify-hook #'erc-fill)
(defun erc-fill-enable ()
"Setup hooks for `erc-fill-mode'."
(interactive)
(add-hook 'erc-insert-modify-hook #'erc-fill)
(add-hook 'erc-send-modify-hook #'erc-fill)) (add-hook 'erc-send-modify-hook #'erc-fill))
((remove-hook 'erc-insert-modify-hook #'erc-fill)
(remove-hook 'erc-send-modify-hook #'erc-fill))) (defun erc-fill-disable ()
"Cleanup hooks, disable `erc-fill-mode'."
(interactive)
(remove-hook 'erc-insert-modify-hook #'erc-fill)
(remove-hook 'erc-send-modify-hook #'erc-fill))
(defcustom erc-fill-prefix nil (defcustom erc-fill-prefix nil
"Values used as `fill-prefix' for `erc-fill-variable'. "Values used as `fill-prefix' for `erc-fill-variable'.
@ -82,29 +91,16 @@ Static Filling with `erc-fill-static-center' of 27:
These two styles are implemented using `erc-fill-variable' and These two styles are implemented using `erc-fill-variable' and
`erc-fill-static'. You can, of course, define your own filling `erc-fill-static'. You can, of course, define your own filling
function. Narrowing to the region in question is in effect while your function. Narrowing to the region in question is in effect while your
function is called. function is called."
A third style resembles static filling but \"wraps\" instead of
fills, thanks to `visual-line-mode' mode, which ERC automatically
enables when this option is `erc-fill-wrap' or when
`erc-fill-wrap-mode' is active. Set `erc-fill-static-center' to
your preferred initial \"prefix\" width. For adjusting the width
during a session, see the command `erc-fill-wrap-nudge'."
:type '(choice (const :tag "Variable Filling" erc-fill-variable) :type '(choice (const :tag "Variable Filling" erc-fill-variable)
(const :tag "Static Filling" erc-fill-static) (const :tag "Static Filling" erc-fill-static)
(const :tag "Dynamic word-wrap" erc-fill-wrap)
function)) function))
(defcustom erc-fill-static-center 27 (defcustom erc-fill-static-center 27
"Number of columns to \"outdent\" the first line of a message. "Column around which all statically filled messages will be centered.
During early message handing, ERC prepends a span of This column denotes the point where the ` ' character between
non-whitespace characters to every message, such as a bracketed <nickname> and the entered text will be put, thus aligning nick
\"<nickname>\" or an `erc-notice-prefix'. The names right and text left."
`erc-fill-function' variants `erc-fill-static' and
`erc-fill-wrap' look to this option to determine the amount of
padding to apply to that portion until the filled (or wrapped)
message content aligns with the indicated column. See also
https://en.wikipedia.org/wiki/Hanging_indent."
:type 'integer) :type 'integer)
(defcustom erc-fill-variable-maximum-indentation 17 (defcustom erc-fill-variable-maximum-indentation 17
@ -134,7 +130,7 @@ You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
(defun erc-fill-static () (defun erc-fill-static ()
"Fills a text such that messages start at column `erc-fill-static-center'." "Fills a text such that messages start at column `erc-fill-static-center'."
(save-restriction (save-match-data
(goto-char (point-min)) (goto-char (point-min))
(looking-at "^\\(\\S-+\\)") (looking-at "^\\(\\S-+\\)")
(let ((nick (match-string 1))) (let ((nick (match-string 1)))
@ -171,343 +167,6 @@ You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
(erc-fill-regarding-timestamp)))) (erc-fill-regarding-timestamp))))
(erc-restore-text-properties))) (erc-restore-text-properties)))
(defvar-local erc-fill--wrap-value nil)
(defvar-local erc-fill--wrap-visual-keys nil)
(defcustom erc-fill-wrap-use-pixels t
"Whether to calculate padding in pixels when possible.
A value of nil means ERC should use columns, which may happen
regardless, depending on the Emacs version. This option only
matters when `erc-fill-wrap-mode' is enabled."
:package-version '(ERC . "5.6") ; FIXME sync on release
:type 'boolean)
(defcustom erc-fill-wrap-visual-keys 'non-input
"Whether to retain keys defined by `visual-line-mode'.
A value of t tells ERC to use movement commands defined by
`visual-line-mode' everywhere in an ERC buffer along with visual
editing commands in the input area. A value of nil means to
never do so. A value of `non-input' tells ERC to act like the
value is nil in the input area and t elsewhere. This option only
plays a role when `erc-fill-wrap-mode' is enabled."
:package-version '(ERC . "5.6") ; FIXME sync on release
:type '(choice (const nil) (const t) (const non-input)))
(defcustom erc-fill-wrap-merge t
"Whether to consolidate messages from the same speaker.
This tells ERC to omit redundant speaker labels for subsequent
messages less than a day apart."
:package-version '(ERC . "5.6") ; FIXME sync on release
:type 'boolean)
(defun erc-fill--wrap-move (normal-cmd visual-cmd arg)
(funcall (pcase erc-fill--wrap-visual-keys
('non-input
(if (>= (point) erc-input-marker) normal-cmd visual-cmd))
('t visual-cmd)
(_ normal-cmd))
arg))
(defun erc-fill--wrap-kill-line (arg)
"Defer to `kill-line' or `kill-visual-line'."
(interactive "P")
;; ERC buffers are read-only outside of the input area, but we run
;; `kill-line' anyway so that users can see the error.
(erc-fill--wrap-move #'kill-line #'kill-visual-line arg))
(defun erc-fill--wrap-beginning-of-line (arg)
"Defer to `move-beginning-of-line' or `beginning-of-visual-line'."
(interactive "^p")
(let ((inhibit-field-text-motion t))
(erc-fill--wrap-move #'move-beginning-of-line
#'beginning-of-visual-line arg))
(if (get-text-property (point) 'erc-prompt)
(goto-char erc-input-marker)
;; Mimic what `move-beginning-of-line' does with invisible text.
(when-let ((erc-fill-wrap-merge)
(empty (get-text-property (point) 'display))
((string-empty-p empty)))
(goto-char (text-property-not-all (point) (pos-eol) 'display empty)))))
(defun erc-fill--wrap-end-of-line (arg)
"Defer to `move-end-of-line' or `end-of-visual-line'."
(interactive "^p")
(erc-fill--wrap-move #'move-end-of-line #'end-of-visual-line arg))
(defun erc-fill-wrap-cycle-visual-movement (arg)
"Cycle through `erc-fill-wrap-visual-keys' styles ARG times.
Go from nil to t to `non-input' and back around, but set internal
state instead of mutating `erc-fill-wrap-visual-keys'. When ARG
is 0, reset to value of `erc-fill-wrap-visual-keys'."
(interactive "^p")
(when (zerop arg)
(setq erc-fill--wrap-visual-keys erc-fill-wrap-visual-keys))
(while (not (zerop arg))
(cl-incf arg (- (abs arg)))
(setq erc-fill--wrap-visual-keys (pcase erc-fill--wrap-visual-keys
('nil t)
('t 'non-input)
('non-input nil))))
(message "erc-fill-wrap movement: %S" erc-fill--wrap-visual-keys))
(defvar-keymap erc-fill-wrap-mode-map ; Compat 29
:doc "Keymap for ERC's `fill-wrap' module."
:parent visual-line-mode-map
"<remap> <kill-line>" #'erc-fill--wrap-kill-line
"<remap> <move-end-of-line>" #'erc-fill--wrap-end-of-line
"<remap> <move-beginning-of-line>" #'erc-fill--wrap-beginning-of-line
"C-c a" #'erc-fill-wrap-cycle-visual-movement
;; Not sure if this is problematic because `erc-bol' takes no args.
"<remap> <erc-bol>" #'erc-fill--wrap-beginning-of-line)
(defvar erc-match-mode)
(defvar erc-button-mode)
(defvar erc-match--hide-fools-offset-bounds)
(defun erc-fill--make-module-dependency-msg (module)
(concat "Enabling default global module `" module "' needed by local"
" module `fill-wrap'. This will impact \C-]all\C-] ERC"
" sessions. Add `" module "' to `erc-modules' to avoid this"
" warning. See Info:\"(erc) Modules\" for more."))
;;;###autoload(put 'fill-wrap 'erc--feature 'erc-fill)
(define-erc-module fill-wrap nil
"Fill style leveraging `visual-line-mode'.
This module displays nickname labels for speakers as overhanging
leftward (and thus right-aligned) to a common offset, as
determined by the option `erc-fill-static-center'. It depends on
the `fill' and `button' modules and assumes the option
`erc-insert-timestamp-function' is `erc-insert-timestamp-right'
or `erc-insert-timestamp-left-and-right' (recommended) so that it
can display right-hand stamps in the right margin. A value of
`erc-insert-timestamp-left' is unsupported. This local module
depends on the global `fill' module. To use it, either include
`fill-wrap' in `erc-modules' or set `erc-fill-function' to
`erc-fill-wrap' (recommended). You can also manually invoke one
of the minor-mode toggles as usual."
((let (msg)
(unless erc-fill-mode
(unless (memq 'fill erc-modules)
(setq msg
;; FIXME use `erc-button--display-error-notice-with-keys'
;; when bug#60933 is ready.
(erc-fill--make-module-dependency-msg "fill")))
(erc-fill-mode +1))
(when erc-fill-wrap-merge
(require 'erc-button)
(unless erc-button-mode
(unless (memq 'button erc-modules)
(setq msg (concat msg (and msg " ")
(erc-fill--make-module-dependency-msg "button"))))
(erc-with-server-buffer
(erc-button-mode +1)))
(add-hook 'erc-button--prev-next-predicate-functions
#'erc-fill--wrap-merged-button-p nil t))
;; Set local value of user option (can we avoid this somehow?)
(unless (eq erc-fill-function #'erc-fill-wrap)
(setq-local erc-fill-function #'erc-fill-wrap))
(when-let* ((vars (or erc--server-reconnecting erc--target-priors))
((alist-get 'erc-fill-wrap-mode vars)))
(setq erc-fill--wrap-visual-keys (alist-get 'erc-fill--wrap-visual-keys
vars)
erc-fill--wrap-value (alist-get 'erc-fill--wrap-value vars)))
(add-function :filter-args (local 'erc-stamp--insert-date-function)
#'erc-fill--wrap-stamp-insert-prefixed-date)
(when (or erc-stamp-mode (memq 'stamp erc-modules))
(erc-stamp--display-margin-mode +1))
(when (or (bound-and-true-p erc-match-mode) (memq 'match erc-modules))
(require 'erc-match)
(setq erc-match--hide-fools-offset-bounds t))
(setq erc-fill--wrap-value
(or erc-fill--wrap-value erc-fill-static-center))
(visual-line-mode +1)
(unless (local-variable-p 'erc-fill--wrap-visual-keys)
(setq erc-fill--wrap-visual-keys erc-fill-wrap-visual-keys))
(when msg
(erc-display-error-notice nil msg))))
((when erc-stamp--display-margin-mode
(erc-stamp--display-margin-mode -1))
(kill-local-variable 'erc-fill--wrap-value)
(kill-local-variable 'erc-fill-function)
(kill-local-variable 'erc-fill--wrap-visual-keys)
(remove-hook 'erc-button--prev-next-predicate-functions
#'erc-fill--wrap-merged-button-p t)
(remove-function (local 'erc-stamp--insert-date-function)
#'erc-fill--wrap-stamp-insert-prefixed-date)
(visual-line-mode -1))
'local)
(defvar-local erc-fill--wrap-length-function nil
"Function to determine length of overhanging characters.
It should return an EXPR as defined by the Info node `(elisp)
Pixel Specification'. This value should represent the width of
the overhang with all faces applied, including any enclosing
brackets (which are not normally fontified) and a trailing space.
It can also return nil to tell ERC to fall back to the default
behavior of taking the length from the first \"word\". This
variable can be converted to a public one if needed by third
parties.")
(defvar-local erc-fill--wrap-last-msg nil)
(defvar-local erc-fill--wrap-max-lull (* 24 60 60))
(defun erc-fill--wrap-continued-message-p ()
(prog1 (and-let*
((m (or erc-fill--wrap-last-msg
(setq erc-fill--wrap-last-msg (point-min-marker))
nil))
((< (1+ (point-min)) (- (point) 2)))
(props (save-restriction
(widen)
(when (eq 'erc-timestamp (field-at-pos m))
(set-marker m (field-end m)))
(and (eq 'PRIVMSG (get-text-property m 'erc-command))
(not (eq (get-text-property m 'font-lock-face)
'erc-action-face))
(cons (get-text-property m 'erc-timestamp)
(get-text-property (1+ m) 'erc-data)))))
(ts (pop props))
((not (time-less-p (erc-stamp--current-time) ts)))
((time-less-p (time-subtract (erc-stamp--current-time) ts)
erc-fill--wrap-max-lull))
(nick (buffer-substring-no-properties
(1+ (point-min)) (- (point) 2)))
(props)
((erc-nick-equal-p (car props) nick))))
(set-marker erc-fill--wrap-last-msg (point-min))))
(defun erc-fill--wrap-stamp-insert-prefixed-date (args)
"Apply `line-prefix' property to args."
(let* ((ts-left (car args)))
(put-text-property 0 (length ts-left) 'line-prefix
`(space :width
(- erc-fill--wrap-value
,(length (string-trim-left ts-left))))
ts-left))
args)
(defun erc-fill-wrap ()
"Use text props to mimic the effect of `erc-fill-static'.
See `erc-fill-wrap-mode' for details."
(unless erc-fill-wrap-mode
(erc-fill-wrap-mode +1))
(save-excursion
(goto-char (point-min))
(let ((len (or (and erc-fill--wrap-length-function
(funcall erc-fill--wrap-length-function))
(progn
(skip-syntax-forward "^-")
(forward-char)
;; Using the `invisible' property might make more
;; sense, but that would require coordination
;; with other modules, like `erc-match'.
(cond ((and erc-fill-wrap-merge
(erc-fill--wrap-continued-message-p))
(put-text-property (point-min) (point)
'display "")
0)
((and erc-fill-wrap-use-pixels
(fboundp 'buffer-text-pixel-size))
(save-restriction
(narrow-to-region (point-min) (point))
(list (car (buffer-text-pixel-size)))))
(t (- (point) (point-min))))))))
;; Leaving out the final newline doesn't seem to affect anything.
(erc-put-text-properties (point-min) (point-max)
'(line-prefix wrap-prefix) nil
`((space :width (- erc-fill--wrap-value ,len))
(space :width erc-fill--wrap-value))))))
;; FIXME use own text property to avoid false positives.
(defun erc-fill--wrap-merged-button-p (point)
(equal "" (get-text-property point 'display)))
;; This is an experimental helper for third-party modules. You could,
;; for example, use this to automatically resize the prefix to a
;; fraction of the window's width on some event change. Another use
;; case would be to fix lines affected by toggling a display-oriented
;; mode, like `display-line-numbers-mode'.
(defun erc-fill--wrap-fix (&optional value)
"Re-wrap from `point-min' to `point-max'.
That is, recalculate the width of all accessible lines and reset
local prefix VALUE when non-nil."
(save-excursion
(when value
(setq erc-fill--wrap-value value))
(let ((inhibit-field-text-motion t)
(inhibit-read-only t))
(goto-char (point-min))
(while (and (zerop (forward-line))
(< (point) (min (point-max) erc-insert-marker)))
(save-restriction
(narrow-to-region (line-beginning-position) (line-end-position))
(erc-fill-wrap))))))
(defun erc-fill--wrap-nudge (arg)
(when (zerop arg)
(setq arg (- erc-fill-static-center erc-fill--wrap-value)))
(cl-incf erc-fill--wrap-value arg)
arg)
(defun erc-fill-wrap-nudge (arg)
"Adjust `erc-fill-wrap' by ARG columns.
Offer to repeat command in a manner similar to
`text-scale-adjust'.
\\`=' Increase indentation by one column
\\`-' Decrease indentation by one column
\\`0' Reset indentation to the default
\\`+' Shift right margin rightward (shrink) by one column
\\`_' Shift right margin leftward (grow) by one column
\\`)' Reset the right margin to the default
Note that misalignment may occur when messages contain
decorations applied by third-party modules. See
`erc-fill--wrap-fix' for a temporary workaround."
(interactive "p")
(unless erc-fill--wrap-value
(cl-assert (not erc-fill-wrap-mode))
(user-error "Minor mode `erc-fill-wrap-mode' disabled"))
(unless (get-buffer-window)
(user-error "Command called in an undisplayed buffer"))
(let* ((total (erc-fill--wrap-nudge arg))
(win-ratio (/ (float (- (window-point) (window-start)))
(- (window-end nil t) (window-start)))))
(when (zerop arg)
(setq arg 1))
(erc-compat-call
set-transient-map
(let ((map (make-sparse-keymap)))
(dolist (key '(?= ?- ?0))
(let ((a (pcase key
(?0 0)
(?- (- (abs arg)))
(_ (abs arg)))))
(define-key map (vector (list key))
(lambda ()
(interactive)
(cl-incf total (erc-fill--wrap-nudge a))
(recenter (round (* win-ratio (window-height))))))))
(dolist (key '(?\) ?_ ?+))
(let ((a (pcase key
(?\) 0)
(?_ (- (abs arg)))
(?+ (abs arg)))))
(define-key map (vector (list key))
(lambda ()
(interactive)
(erc-stamp--adjust-right-margin (- a))
(recenter (round (* win-ratio (window-height))))))))
map)
t
(lambda ()
(message "Fill prefix: %d (%+d col%s)"
erc-fill--wrap-value total (if (> (abs total) 1) "s" "")))
"Use %k for further adjustment"
1)
(recenter (round (* win-ratio (window-height))))))
(defun erc-fill-regarding-timestamp () (defun erc-fill-regarding-timestamp ()
"Fills a text such that messages start at column `erc-fill-static-center'." "Fills a text such that messages start at column `erc-fill-static-center'."
(fill-region (point-min) (point-max) t t) (fill-region (point-min) (point-max) t t)

View file

@ -29,13 +29,30 @@
;;; Code: ;;; Code:
;;; Imenu support
(eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'cl-lib))
(require 'erc) (require 'erc-common)
(declare-function fringe-columns "fringe" (side &optional real)) (defvar erc-controls-highlight-regexp)
(declare-function pulse-available-p "pulse" nil) (defvar erc-controls-remove-regexp)
(declare-function pulse-momentary-highlight-overlay "pulse" (o &optional face)) (defvar erc-input-marker)
(defvar erc-insert-marker)
(defvar erc-server-process)
(defvar erc-modules)
(defvar erc-log-p)
(declare-function erc-buffer-list "erc" (&optional predicate proc))
(declare-function erc-error "erc" (&rest args))
(declare-function erc-extract-command-from-line "erc" (line))
(declare-function erc-beg-of-input-line "erc" nil)
(defun erc-imenu-setup ()
"Setup Imenu support in an ERC buffer."
(setq-local imenu-create-index-function #'erc-create-imenu-index))
(add-hook 'erc-mode-hook #'erc-imenu-setup)
(autoload 'erc-create-imenu-index "erc-imenu" "Imenu index creation function")
;;; Automatically scroll to bottom ;;; Automatically scroll to bottom
(defcustom erc-input-line-position nil (defcustom erc-input-line-position nil
@ -48,7 +65,6 @@ argument to `recenter'."
:group 'erc-display :group 'erc-display
:type '(choice integer (const nil))) :type '(choice integer (const nil)))
;;;###autoload(autoload 'erc-scrolltobottom-mode "erc-goodies" nil t)
(define-erc-module scrolltobottom nil (define-erc-module scrolltobottom nil
"This mode causes the prompt to stay at the end of the window." "This mode causes the prompt to stay at the end of the window."
((add-hook 'erc-mode-hook #'erc-add-scroll-to-bottom) ((add-hook 'erc-mode-hook #'erc-add-scroll-to-bottom)
@ -100,7 +116,6 @@ variable `erc-input-line-position'."
(recenter (or erc-input-line-position -1))))))) (recenter (or erc-input-line-position -1)))))))
;;; Make read only ;;; Make read only
;;;###autoload(autoload 'erc-readonly-mode "erc-goodies" nil t)
(define-erc-module readonly nil (define-erc-module readonly nil
"This mode causes all inserted text to be read-only." "This mode causes all inserted text to be read-only."
((add-hook 'erc-insert-post-hook #'erc-make-read-only) ((add-hook 'erc-insert-post-hook #'erc-make-read-only)
@ -116,7 +131,6 @@ Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'."
(put-text-property (point-min) (point-max) 'rear-nonsticky t)) (put-text-property (point-min) (point-max) 'rear-nonsticky t))
;;; Move to prompt when typing text ;;; Move to prompt when typing text
;;;###autoload(autoload 'erc-move-to-prompt-mode "erc-goodies" nil t)
(define-erc-module move-to-prompt nil (define-erc-module move-to-prompt nil
"This mode causes the point to be moved to the prompt when typing text." "This mode causes the point to be moved to the prompt when typing text."
((add-hook 'erc-mode-hook #'erc-move-to-prompt-setup) ((add-hook 'erc-mode-hook #'erc-move-to-prompt-setup)
@ -141,160 +155,11 @@ Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'."
(add-hook 'pre-command-hook #'erc-move-to-prompt nil t)) (add-hook 'pre-command-hook #'erc-move-to-prompt nil t))
;;; Keep place in unvisited channels ;;; Keep place in unvisited channels
;;;###autoload(autoload 'erc-keep-place-mode "erc-goodies" nil t)
(define-erc-module keep-place nil (define-erc-module keep-place nil
"Leave point above un-viewed text in other channels." "Leave point above un-viewed text in other channels."
((add-hook 'erc-insert-pre-hook #'erc-keep-place)) ((add-hook 'erc-insert-pre-hook #'erc-keep-place))
((remove-hook 'erc-insert-pre-hook #'erc-keep-place))) ((remove-hook 'erc-insert-pre-hook #'erc-keep-place)))
(defcustom erc-keep-place-indicator-style t
"Flavor of visual indicator applied to kept place.
For use with the `keep-place-indicator' module. A value of `arrow'
displays an arrow in the left fringe or margin. When it's
`face', ERC adds the face `erc-keep-place-indicator-line' to the
appropriate line. A value of t does both."
:group 'erc
:package-version '(ERC . "5.6")
:type '(choice (const t) (const server) (const target)))
(defcustom erc-keep-place-indicator-buffer-type t
"ERC buffer type in which to display `keep-place-indicator'.
A value of t means \"all\" ERC buffers."
:group 'erc
:package-version '(ERC . "5.6")
:type '(choice (const t) (const server) (const target)))
(defcustom erc-keep-place-indicator-follow nil
"Whether to sync visual kept place to window's top when reading.
For use with `erc-keep-place-indicator-mode'."
:group 'erc
:package-version '(ERC . "5.6")
:type 'boolean)
(defface erc-keep-place-indicator-line
'((((class color) (min-colors 88) (background light)
(supports :underline (:style wave)))
(:underline (:color "PaleGreen3" :style wave)))
(((class color) (min-colors 88) (background dark)
(supports :underline (:style wave)))
(:underline (:color "PaleGreen1" :style wave)))
(t :underline t))
"Face for option `erc-keep-place-indicator-style'."
:group 'erc-faces)
(defface erc-keep-place-indicator-arrow
'((((class color) (min-colors 88) (background light))
(:foreground "PaleGreen3"))
(((class color) (min-colors 88) (background dark))
(:foreground "PaleGreen1"))
(t :inherit fringe))
"Face for arrow value of option `erc-keep-place-indicator-style'."
:group 'erc-faces)
(defvar-local erc--keep-place-indicator-overlay nil
"Overlay for `erc-keep-place-indicator-mode'.")
(defun erc--keep-place-indicator-on-window-configuration-change ()
"Maybe sync `erc--keep-place-indicator-overlay'.
Specifically, do so unless switching to or from another window in
the active frame."
(when erc-keep-place-indicator-follow
(unless (or (minibuffer-window-active-p (minibuffer-window))
(eq (window-old-buffer) (current-buffer)))
(when (< (overlay-end erc--keep-place-indicator-overlay)
(window-start)
erc-insert-marker)
(erc-keep-place-move (window-start))))))
(defun erc--keep-place-indicator-setup ()
"Initialize buffer for maintaining `erc--keep-place-indicator-overlay'."
(require 'fringe)
(setq erc--keep-place-indicator-overlay
(if-let* ((vars (or erc--server-reconnecting erc--target-priors))
((alist-get 'erc-keep-place-indicator-mode vars)))
(alist-get 'erc--keep-place-indicator-overlay vars)
(make-overlay 0 0)))
(add-hook 'window-configuration-change-hook
#'erc--keep-place-indicator-on-window-configuration-change nil t)
(when-let* (((memq erc-keep-place-indicator-style '(t arrow)))
(display (if (zerop (fringe-columns 'left))
`((margin left-margin) ,overlay-arrow-string)
'(left-fringe right-triangle
erc-keep-place-indicator-arrow)))
(bef (propertize " " 'display display)))
(overlay-put erc--keep-place-indicator-overlay 'before-string bef))
(when (memq erc-keep-place-indicator-style '(t face))
(overlay-put erc--keep-place-indicator-overlay 'face
'erc-keep-place-indicator-line)))
;;;###autoload(put 'keep-place-indicator 'erc--feature 'erc-goodies)
(define-erc-module keep-place-indicator nil
"`keep-place' with a fringe arrow and/or highlighted face."
((unless erc-keep-place-mode
(unless (memq 'keep-place erc-modules)
;; FIXME use `erc-button--display-error-notice-with-keys'
;; to display this message when bug#60933 is ready.
(erc-display-error-notice
nil (concat
"Local module `keep-place-indicator' needs module `keep-place'."
" Enabling now. This will affect \C-]all\C-] ERC sessions."
" Add `keep-place' to `erc-modules' to silence this message.")))
(erc-keep-place-mode +1))
(if (pcase erc-keep-place-indicator-buffer-type
('target erc--target)
('server (not erc--target))
('t t))
(erc--keep-place-indicator-setup)
(setq erc-keep-place-indicator-mode nil)))
((when erc--keep-place-indicator-overlay
(delete-overlay erc--keep-place-indicator-overlay)
(remove-hook 'window-configuration-change-hook
#'erc--keep-place-indicator-on-window-configuration-change t)
(kill-local-variable 'erc--keep-place-indicator-overlay)))
'local)
(defun erc-keep-place-move (pos)
"Move keep-place indicator to current line or POS.
For use with `keep-place-indicator' module. When called
interactively, interpret POS as an offset. Specifically, when
POS is a raw prefix arg, like (4), move the indicator to the
window's last line. When it's the minus sign, put it on the
window's first line. Interpret an integer as an offset in lines."
(interactive
(progn
(unless erc-keep-place-indicator-mode
(user-error "`erc-keep-place-indicator-mode' not enabled"))
(list (pcase current-prefix-arg
((and (pred integerp) v)
(save-excursion
(let ((inhibit-field-text-motion t))
(forward-line v)
(point))))
(`(,_) (1- (min erc-insert-marker (window-end))))
('- (min (1- erc-insert-marker) (window-start)))))))
(save-excursion
(let ((inhibit-field-text-motion t))
(when pos
(goto-char pos))
(move-overlay erc--keep-place-indicator-overlay
(line-beginning-position)
(line-end-position)))))
(defun erc-keep-place-goto ()
"Jump to keep-place indicator.
For use with `keep-place-indicator' module."
(interactive
(prog1 nil
(unless erc-keep-place-indicator-mode
(user-error "`erc-keep-place-indicator-mode' not enabled"))
(deactivate-mark)
(push-mark)))
(goto-char (overlay-start erc--keep-place-indicator-overlay))
(recenter (truncate (* (window-height) 0.25)) t)
(require 'pulse)
(when (pulse-available-p)
(pulse-momentary-highlight-overlay erc--keep-place-indicator-overlay)))
(defun erc-keep-place (_ignored) (defun erc-keep-place (_ignored)
"Move point away from the last line in a non-selected ERC buffer." "Move point away from the last line in a non-selected ERC buffer."
(when (and (not (eq (window-buffer (selected-window)) (when (and (not (eq (window-buffer (selected-window))
@ -303,11 +168,6 @@ For use with `keep-place-indicator' module."
(deactivate-mark) (deactivate-mark)
(goto-char (erc-beg-of-input-line)) (goto-char (erc-beg-of-input-line))
(forward-line -1) (forward-line -1)
(when erc-keep-place-indicator-mode
(unless (or (minibuffer-window-active-p (selected-window))
(and (frame-visible-p (selected-frame))
(get-buffer-window (current-buffer) (selected-frame))))
(erc-keep-place-move nil)))
;; if `switch-to-buffer-preserve-window-point' is set, ;; if `switch-to-buffer-preserve-window-point' is set,
;; we cannot rely on point being saved, and must commit ;; we cannot rely on point being saved, and must commit
;; it to window-prev-buffers. ;; it to window-prev-buffers.
@ -333,14 +193,12 @@ For use with `keep-place-indicator' module."
If a command's function symbol is in this list, the typed command If a command's function symbol is in this list, the typed command
does not appear in the ERC buffer after the user presses ENTER.") does not appear in the ERC buffer after the user presses ENTER.")
;;;###autoload(autoload 'erc-noncommands-mode "erc-goodies" nil t)
(define-erc-module noncommands nil (define-erc-module noncommands nil
"This mode distinguishes non-commands. "This mode distinguishes non-commands.
Commands listed in `erc-insert-this' know how to display Commands listed in `erc-insert-this' know how to display
themselves." themselves."
((add-hook 'erc--input-review-functions #'erc-send-distinguish-noncommands)) ((add-hook 'erc-pre-send-functions #'erc-send-distinguish-noncommands))
((remove-hook 'erc--input-review-functions ((remove-hook 'erc-pre-send-functions #'erc-send-distinguish-noncommands)))
#'erc-send-distinguish-noncommands)))
(defun erc-send-distinguish-noncommands (state) (defun erc-send-distinguish-noncommands (state)
"If STR is an ERC non-command, set `insertp' in STATE to nil." "If STR is an ERC non-command, set `insertp' in STATE to nil."
@ -393,12 +251,6 @@ The value `erc-interpret-controls-p' must also be t for this to work."
"ERC inverse face." "ERC inverse face."
:group 'erc-faces) :group 'erc-faces)
(defface erc-spoiler-face
'((((background light)) :foreground "DimGray" :background "DimGray")
(((background dark)) :foreground "LightGray" :background "LightGray"))
"ERC spoiler face."
:group 'erc-faces)
(defface erc-underline-face '((t :underline t)) (defface erc-underline-face '((t :underline t))
"ERC underline face." "ERC underline face."
:group 'erc-faces) :group 'erc-faces)
@ -501,38 +353,19 @@ The value `erc-interpret-controls-p' must also be t for this to work."
"ERC face." "ERC face."
:group 'erc-faces) :group 'erc-faces)
;; https://lists.gnu.org/archive/html/emacs-erc/2021-07/msg00005.html
(defvar erc--controls-additional-colors
["#470000" "#472100" "#474700" "#324700" "#004700" "#00472c"
"#004747" "#002747" "#000047" "#2e0047" "#470047" "#47002a"
"#740000" "#743a00" "#747400" "#517400" "#007400" "#007449"
"#007474" "#004074" "#000074" "#4b0074" "#740074" "#740045"
"#b50000" "#b56300" "#b5b500" "#7db500" "#00b500" "#00b571"
"#00b5b5" "#0063b5" "#0000b5" "#7500b5" "#b500b5" "#b5006b"
"#ff0000" "#ff8c00" "#ffff00" "#b2ff00" "#00ff00" "#00ffa0"
"#00ffff" "#008cff" "#0000ff" "#a500ff" "#ff00ff" "#ff0098"
"#ff5959" "#ffb459" "#ffff71" "#cfff60" "#6fff6f" "#65ffc9"
"#6dffff" "#59b4ff" "#5959ff" "#c459ff" "#ff66ff" "#ff59bc"
"#ff9c9c" "#ffd39c" "#ffff9c" "#e2ff9c" "#9cff9c" "#9cffdb"
"#9cffff" "#9cd3ff" "#9c9cff" "#dc9cff" "#ff9cff" "#ff94d3"
"#000000" "#131313" "#282828" "#363636" "#4d4d4d" "#656565"
"#818181" "#9f9f9f" "#bcbcbc" "#e2e2e2" "#ffffff"])
(defun erc-get-bg-color-face (n) (defun erc-get-bg-color-face (n)
"Fetches the right face for background color N (0-15)." "Fetches the right face for background color N (0-15)."
(if (stringp n) (setq n (string-to-number n))) (if (stringp n) (setq n (string-to-number n)))
(if (not (numberp n)) (if (not (numberp n))
(prog1 'default (prog1 'default
(erc-error "erc-get-bg-color-face: n is NaN: %S" n)) (erc-error "erc-get-bg-color-face: n is NaN: %S" n))
(when (> n 99) (when (> n 16)
(erc-log (format " Wrong color: %s" n)) (erc-log (format " Wrong color: %s" n))
(setq n (mod n 16))) (setq n (mod n 16)))
(cond (cond
((and (>= n 0) (< n 16)) ((and (>= n 0) (< n 16))
(intern (concat "bg:erc-color-face" (number-to-string n)))) (intern (concat "bg:erc-color-face" (number-to-string n))))
((< 15 n 99) (t (erc-log (format " Wrong color: %s" n)) 'default))))
(list :background (aref erc--controls-additional-colors (- n 16))))
(t (erc-log (format " Wrong color: %s" n)) '(default)))))
(defun erc-get-fg-color-face (n) (defun erc-get-fg-color-face (n)
"Fetches the right face for foreground color N (0-15)." "Fetches the right face for foreground color N (0-15)."
@ -540,44 +373,20 @@ The value `erc-interpret-controls-p' must also be t for this to work."
(if (not (numberp n)) (if (not (numberp n))
(prog1 'default (prog1 'default
(erc-error "erc-get-fg-color-face: n is NaN: %S" n)) (erc-error "erc-get-fg-color-face: n is NaN: %S" n))
(when (> n 99) (when (> n 16)
(erc-log (format " Wrong color: %s" n)) (erc-log (format " Wrong color: %s" n))
(setq n (mod n 16))) (setq n (mod n 16)))
(cond (cond
((and (>= n 0) (< n 16)) ((and (>= n 0) (< n 16))
(intern (concat "fg:erc-color-face" (number-to-string n)))) (intern (concat "fg:erc-color-face" (number-to-string n))))
((< 15 n 99) (t (erc-log (format " Wrong color: %s" n)) 'default))))
(list :foreground (aref erc--controls-additional-colors (- n 16))))
(t (erc-log (format " Wrong color: %s" n)) '(default)))))
;;;###autoload(autoload 'erc-irccontrols-mode "erc-goodies" nil t)
(define-erc-module irccontrols nil (define-erc-module irccontrols nil
"This mode enables the interpretation of IRC control chars." "This mode enables the interpretation of IRC control chars."
((add-hook 'erc-insert-modify-hook #'erc-controls-highlight) ((add-hook 'erc-insert-modify-hook #'erc-controls-highlight)
(add-hook 'erc-send-modify-hook #'erc-controls-highlight) (add-hook 'erc-send-modify-hook #'erc-controls-highlight))
(erc--modify-local-map t "C-c C-c" #'erc-toggle-interpret-controls))
((remove-hook 'erc-insert-modify-hook #'erc-controls-highlight) ((remove-hook 'erc-insert-modify-hook #'erc-controls-highlight)
(remove-hook 'erc-send-modify-hook #'erc-controls-highlight) (remove-hook 'erc-send-modify-hook #'erc-controls-highlight)))
(erc--modify-local-map nil "C-c C-c" #'erc-toggle-interpret-controls)))
;; These patterns were moved here to circumvent compiler warnings but
;; otherwise translated verbatim from their original string-literal
;; definitions (minus a small bug fix to satisfy newly added tests).
(defvar erc-controls-remove-regexp
(rx (or ?\C-b ?\C-\] ?\C-_ ?\C-v ?\C-g ?\C-o
(: ?\C-c (? (any "0-9")) (? (any "0-9"))
(? (group ?, (any "0-9") (? (any "0-9")))))))
"Regular expression matching control characters to remove.")
;; Before the change to `rx', group 3 used to be a sibling of group 2.
;; This was assumed to be a bug. A few minor simplifications were
;; also performed. If incorrect, please admonish.
(defvar erc-controls-highlight-regexp
(rx (group (or ?\C-b ?\C-\] ?\C-v ?\C-_ ?\C-g ?\C-o
(: ?\C-c (? (group (** 1 2 (any "0-9")))
(? (group ?, (group (** 1 2 (any "0-9")))))))))
(group (* (not (any ?\C-b ?\C-c ?\C-g ?\n ?\C-o ?\C-v ?\C-\] ?\C-_)))))
"Regular expression matching control chars to highlight.")
(defun erc-controls-interpret (str) (defun erc-controls-interpret (str)
"Return a copy of STR after dealing with IRC control characters. "Return a copy of STR after dealing with IRC control characters.
@ -631,7 +440,6 @@ See `erc-interpret-controls-p' and `erc-interpret-mirc-color' for options."
s)) s))
(t s))))) (t s)))))
;;;###autoload
(defun erc-controls-strip (str) (defun erc-controls-strip (str)
"Return a copy of STR with all IRC control characters removed." "Return a copy of STR with all IRC control characters removed."
(when str (when str
@ -640,6 +448,16 @@ See `erc-interpret-controls-p' and `erc-interpret-mirc-color' for options."
(setq s (replace-match "" nil nil s))) (setq s (replace-match "" nil nil s)))
s))) s)))
(defvar erc-controls-remove-regexp
"\C-b\\|\C-]\\|\C-_\\|\C-v\\|\C-g\\|\C-o\\|\C-c[0-9]?[0-9]?\\(,[0-9][0-9]?\\)?"
"Regular expression which matches control characters to remove.")
(defvar erc-controls-highlight-regexp
(concat "\\(\C-b\\|\C-]\\|\C-v\\|\C-_\\|\C-g\\|\C-o\\|"
"\C-c\\([0-9][0-9]?\\)?\\(,\\([0-9][0-9]?\\)\\)?\\)"
"\\([^\C-b\C-]\C-v\C-_\C-c\C-g\C-o\n]*\\)")
"Regular expression which matches control chars and the text to highlight.")
(defun erc-controls-highlight () (defun erc-controls-highlight ()
"Highlight IRC control chars in the buffer. "Highlight IRC control chars in the buffer.
This is useful for `erc-insert-modify-hook' and `erc-send-modify-hook'. This is useful for `erc-insert-modify-hook' and `erc-send-modify-hook'.
@ -696,13 +514,6 @@ Also see `erc-interpret-controls-p' and `erc-interpret-mirc-color'."
"Prepend properties from IRC control characters between FROM and TO. "Prepend properties from IRC control characters between FROM and TO.
If optional argument STR is provided, apply to STR, otherwise prepend properties If optional argument STR is provided, apply to STR, otherwise prepend properties
to a region in the current buffer." to a region in the current buffer."
(if (and fg bg (equal fg bg))
(progn
(setq fg 'erc-spoiler-face
bg nil)
(put-text-property from to 'mouse-face 'erc-inverse-face str))
(when fg (setq fg (erc-get-fg-color-face fg)))
(when bg (setq bg (erc-get-bg-color-face bg))))
(font-lock-prepend-text-property (font-lock-prepend-text-property
from from
to to
@ -720,10 +531,10 @@ to a region in the current buffer."
'(erc-underline-face) '(erc-underline-face)
nil) nil)
(if fg (if fg
(list fg) (list (erc-get-fg-color-face fg))
nil) nil)
(if bg (if bg
(list bg) (list (erc-get-bg-color-face bg))
nil)) nil))
str) str)
str) str)
@ -742,7 +553,6 @@ Else interpretation is turned off."
(if erc-interpret-controls-p "ON" "OFF"))) (if erc-interpret-controls-p "ON" "OFF")))
;; Smiley ;; Smiley
;;;###autoload(autoload 'erc-smiley-mode "erc-goodies" nil t)
(define-erc-module smiley nil (define-erc-module smiley nil
"This mode translates text-smileys such as :-) into pictures. "This mode translates text-smileys such as :-) into pictures.
This requires the function `smiley-region', which is defined in This requires the function `smiley-region', which is defined in
@ -759,7 +569,6 @@ This function should be used with `erc-insert-modify-hook'."
(smiley-region (point-min) (point-max)))) (smiley-region (point-min) (point-max))))
;; Unmorse ;; Unmorse
;;;###autoload(autoload 'erc-unmorse-mode "erc-goodies" nil t)
(define-erc-module unmorse nil (define-erc-module unmorse nil
"This mode causes morse code in the current channel to be unmorsed." "This mode causes morse code in the current channel to be unmorsed."
((add-hook 'erc-insert-modify-hook #'erc-unmorse)) ((add-hook 'erc-insert-modify-hook #'erc-unmorse))
@ -802,7 +611,3 @@ servers. If called from a program, PROC specifies the server process."
(provide 'erc-goodies) (provide 'erc-goodies)
;;; erc-goodies.el ends here ;;; erc-goodies.el ends here
;; Local Variables:
;; generated-autoload-file: "erc-loaddefs.el"
;; End:

Some files were not shown because too many files have changed in this diff Show more